use strict context boundaries and remove all n+1 queries
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2023-03-18 21:06:00 -04:00
parent 0b7146ba32
commit a54cf8b87d
84 changed files with 4345 additions and 3090 deletions

View File

@ -4,7 +4,8 @@ defmodule CanneryWeb.ContainerLive.EditTagsComponent do
"""
use CanneryWeb, :live_component
alias Cannery.{Accounts.User, Containers, Containers.Container, Tags, Tags.Tag}
alias Cannery.{Accounts.User, Containers}
alias Cannery.Containers.{Container, Tag}
alias Phoenix.LiveView.Socket
@impl true
@ -22,7 +23,7 @@ defmodule CanneryWeb.ContainerLive.EditTagsComponent do
assigns,
socket
) do
tags = Tags.list_tags(current_user)
tags = Containers.list_tags(current_user)
{:ok, socket |> assign(assigns) |> assign(:tags, tags)}
end

View File

@ -35,17 +35,17 @@ defmodule CanneryWeb.ContainerLive.FormComponent do
container_params
) do
changeset_action =
cond do
action in [:new, :clone] -> :insert
action == :edit -> :update
case action do
create when create in [:new, :clone] -> :insert
:edit -> :update
end
changeset =
cond do
action in [:new, :clone] ->
case action do
create when create in [:new, :clone] ->
container |> Container.create_changeset(user, container_params)
action == :edit ->
:edit ->
container |> Container.update_changeset(container_params)
end

View File

@ -4,7 +4,7 @@ defmodule CanneryWeb.ContainerLive.Index do
"""
use CanneryWeb, :live_view
alias Cannery.{Containers, Containers.Container, Repo}
alias Cannery.{Containers, Containers.Container}
alias Ecto.Changeset
@impl true
@ -22,10 +22,7 @@ defmodule CanneryWeb.ContainerLive.Index do
end
defp apply_action(%{assigns: %{current_user: current_user}} = socket, :edit, %{"id" => id}) do
%{name: container_name} =
container =
Containers.get_container!(id, current_user)
|> Repo.preload([:tags, :ammo_groups])
%{name: container_name} = container = Containers.get_container!(id, current_user)
socket
|> assign(page_title: gettext("Edit %{name}", name: container_name), container: container)
@ -61,9 +58,7 @@ defmodule CanneryWeb.ContainerLive.Index do
end
defp apply_action(%{assigns: %{current_user: current_user}} = socket, :edit_tags, %{"id" => id}) do
%{name: container_name} =
container =
Containers.get_container!(id, current_user) |> Repo.preload([:tags, :ammo_groups])
%{name: container_name} = container = Containers.get_container!(id, current_user)
page_title = gettext("Edit %{name} tags", name: container_name)
socket |> assign(page_title: page_title, container: container)
@ -119,10 +114,6 @@ defmodule CanneryWeb.ContainerLive.Index do
end
defp display_containers(%{assigns: %{search: search, current_user: current_user}} = socket) do
containers =
Containers.list_containers(search, current_user)
|> Repo.preload([:tags, :ammo_groups])
socket |> assign(:containers, containers)
socket |> assign(:containers, Containers.list_containers(search, current_user))
end
end

View File

@ -108,7 +108,11 @@
</.live_component>
<% else %>
<div class="w-full flex flex-row flex-wrap justify-center items-stretch">
<.container_card :for={container <- @containers} container={container}>
<.container_card
:for={container <- @containers}
container={container}
current_user={@current_user}
>
<:tag_actions>
<div class="mx-4 my-2">
<.link
@ -162,29 +166,30 @@
<% end %>
</div>
<.modal
:if={@live_action in [:new, :edit, :clone]}
return_to={Routes.container_index_path(Endpoint, :index)}
>
<.live_component
module={CanneryWeb.ContainerLive.FormComponent}
id={@container.id || :new}
title={@page_title}
action={@live_action}
container={@container}
return_to={Routes.container_index_path(Endpoint, :index)}
current_user={@current_user}
/>
</.modal>
<.modal :if={@live_action == :edit_tags} return_to={Routes.container_index_path(Endpoint, :index)}>
<.live_component
module={CanneryWeb.ContainerLive.EditTagsComponent}
id={@container.id}
title={@page_title}
action={@live_action}
container={@container}
current_path={Routes.container_index_path(Endpoint, :edit_tags, @container)}
current_user={@current_user}
/>
</.modal>
<%= case @live_action do %>
<% modifying when modifying in [:new, :edit, :clone] -> %>
<.modal return_to={Routes.container_index_path(Endpoint, :index)}>
<.live_component
module={CanneryWeb.ContainerLive.FormComponent}
id={@container.id || :new}
title={@page_title}
action={@live_action}
container={@container}
return_to={Routes.container_index_path(Endpoint, :index)}
current_user={@current_user}
/>
</.modal>
<% :edit_tags -> %>
<.modal return_to={Routes.container_index_path(Endpoint, :index)}>
<.live_component
module={CanneryWeb.ContainerLive.EditTagsComponent}
id={@container.id}
title={@page_title}
action={@live_action}
container={@container}
current_path={Routes.container_index_path(Endpoint, :edit_tags, @container)}
current_user={@current_user}
/>
</.modal>
<% _ -> %>
<% end %>

View File

@ -4,7 +4,7 @@ defmodule CanneryWeb.ContainerLive.Show do
"""
use CanneryWeb, :live_view
alias Cannery.{Accounts.User, Ammo, Containers, Containers.Container, Repo, Tags}
alias Cannery.{Accounts.User, ActivityLog, Ammo, Containers, Containers.Container}
alias CanneryWeb.Endpoint
alias Ecto.Changeset
alias Phoenix.LiveView.Socket
@ -30,7 +30,7 @@ defmodule CanneryWeb.ContainerLive.Show do
%{assigns: %{container: container, current_user: current_user}} = socket
) do
socket =
case Tags.get_tag(tag_id, current_user) do
case Containers.get_tag(tag_id, current_user) do
{:ok, tag} ->
_count = Containers.remove_tag!(container, tag, current_user)
@ -42,8 +42,8 @@ defmodule CanneryWeb.ContainerLive.Show do
socket |> put_flash(:info, prompt) |> render_container()
{:error, error_string} ->
socket |> put_flash(:error, error_string)
{:error, :not_found} ->
socket |> put_flash(:error, dgettext("errors", "Tag not found"))
end
{:noreply, socket}
@ -96,12 +96,11 @@ defmodule CanneryWeb.ContainerLive.Show do
id,
current_user
) do
%{name: container_name} =
container =
Containers.get_container!(id, current_user)
|> Repo.preload([:tags], force: true)
%{name: container_name} = container = Containers.get_container!(id, current_user)
ammo_groups = Ammo.list_ammo_groups_for_container(container, current_user, show_used)
original_counts = ammo_groups |> Ammo.get_original_counts(current_user)
cprs = ammo_groups |> Ammo.get_cprs(current_user)
last_used_dates = ammo_groups |> ActivityLog.get_last_used_dates(current_user)
page_title =
case live_action do
@ -110,7 +109,16 @@ defmodule CanneryWeb.ContainerLive.Show do
:edit_tags -> gettext("Edit %{name} tags", name: container_name)
end
socket |> assign(container: container, ammo_groups: ammo_groups, page_title: page_title)
socket
|> assign(
container: container,
round_count: Ammo.get_round_count_for_container!(container, current_user),
ammo_groups: ammo_groups,
original_counts: original_counts,
cprs: cprs,
last_used_dates: last_used_dates,
page_title: page_title
)
end
@spec render_container(Socket.t()) :: Socket.t()

View File

@ -20,21 +20,18 @@
<%= unless @ammo_groups |> Enum.empty?() do %>
<span class="rounded-lg title text-lg">
<%= if @show_used do %>
<%= gettext("Total packs:") %>
<% else %>
<%= gettext("Packs:") %>
<% end %>
<%= gettext("Packs:") %>
<%= @ammo_groups |> Enum.reject(fn %{count: count} -> count in [0, nil] end) |> Enum.count() %>
</span>
<span :if={@show_used} class="rounded-lg title text-lg">
<%= gettext("Total packs:") %>
<%= Enum.count(@ammo_groups) %>
</span>
<span class="rounded-lg title text-lg">
<%= if @show_used do %>
<%= gettext("Total rounds:") %>
<% else %>
<%= gettext("Rounds:") %>
<% end %>
<%= @container |> Containers.get_container_rounds!() %>
<%= gettext("Rounds:") %>
<%= @round_count %>
</span>
<% end %>
@ -130,40 +127,45 @@
</.live_component>
<% else %>
<div class="flex flex-wrap justify-center items-stretch">
<.ammo_group_card :for={ammo_group <- @ammo_groups} ammo_group={ammo_group} />
<.ammo_group_card
:for={%{id: ammo_group_id} = ammo_group <- @ammo_groups}
ammo_group={ammo_group}
original_count={Map.fetch!(@original_counts, ammo_group_id)}
cpr={Map.get(@cprs, ammo_group_id)}
last_used_date={Map.get(@last_used_dates, ammo_group_id)}
current_user={@current_user}
/>
</div>
<% end %>
<% end %>
</div>
</div>
<.modal
:if={@live_action == :edit}
return_to={Routes.container_show_path(Endpoint, :show, @container)}
>
<.live_component
module={CanneryWeb.ContainerLive.FormComponent}
id={@container.id}
title={@page_title}
action={@live_action}
container={@container}
return_to={Routes.container_show_path(Endpoint, :show, @container)}
current_user={@current_user}
/>
</.modal>
<.modal
:if={@live_action == :edit_tags}
return_to={Routes.container_show_path(Endpoint, :show, @container)}
>
<.live_component
module={CanneryWeb.ContainerLive.EditTagsComponent}
id={@container.id}
title={@page_title}
action={@live_action}
container={@container}
return_to={Routes.container_show_path(Endpoint, :show, @container)}
current_path={Routes.container_show_path(Endpoint, :edit_tags, @container)}
current_user={@current_user}
/>
</.modal>
<%= case @live_action do %>
<% :edit -> %>
<.modal return_to={Routes.container_show_path(Endpoint, :show, @container)}>
<.live_component
module={CanneryWeb.ContainerLive.FormComponent}
id={@container.id}
title={@page_title}
action={@live_action}
container={@container}
return_to={Routes.container_show_path(Endpoint, :show, @container)}
current_user={@current_user}
/>
</.modal>
<% :edit_tags -> %>
<.modal return_to={Routes.container_show_path(Endpoint, :show, @container)}>
<.live_component
module={CanneryWeb.ContainerLive.EditTagsComponent}
id={@container.id}
title={@page_title}
action={@live_action}
container={@container}
return_to={Routes.container_show_path(Endpoint, :show, @container)}
current_path={Routes.container_show_path(Endpoint, :edit_tags, @container)}
current_user={@current_user}
/>
</.modal>
<% _ -> %>
<% end %>