add container index table
This commit is contained in:
		| @@ -6,11 +6,11 @@ defmodule CanneryWeb.ContainerLive.Index do | ||||
|   use CanneryWeb, :live_view | ||||
|   import CanneryWeb.Components.ContainerCard | ||||
|   alias Cannery.{Containers, Containers.Container, Repo} | ||||
|   alias CanneryWeb.Endpoint | ||||
|   alias CanneryWeb.{Components.TagCard, Endpoint} | ||||
|   alias Ecto.Changeset | ||||
|  | ||||
|   @impl true | ||||
|   def mount(_params, _session, socket), do: {:ok, socket} | ||||
|   def mount(_params, _session, socket), do: {:ok, socket |> assign(view_table: false)} | ||||
|  | ||||
|   @impl true | ||||
|   def handle_params(params, _url, %{assigns: %{live_action: live_action}} = socket) do | ||||
| @@ -33,8 +33,20 @@ defmodule CanneryWeb.ContainerLive.Index do | ||||
|  | ||||
|   defp apply_action(socket, :index, _params) do | ||||
|     socket | ||||
|     |> assign(:page_title, gettext("Containers")) | ||||
|     |> assign(:container, nil) | ||||
|     |> assign( | ||||
|       page_title: gettext("Containers"), | ||||
|       container: nil | ||||
|     ) | ||||
|     |> display_containers() | ||||
|   end | ||||
|  | ||||
|   defp apply_action(socket, :table, _params) do | ||||
|     socket | ||||
|     |> assign( | ||||
|       page_title: gettext("Containers"), | ||||
|       container: nil, | ||||
|       view_table: true | ||||
|     ) | ||||
|     |> display_containers() | ||||
|   end | ||||
|  | ||||
| @@ -83,10 +95,127 @@ defmodule CanneryWeb.ContainerLive.Index do | ||||
|     {:noreply, socket} | ||||
|   end | ||||
|  | ||||
|   @impl true | ||||
|   def handle_event("toggle_table", _params, %{assigns: %{view_table: view_table}} = socket) do | ||||
|     new_path = | ||||
|       if view_table, | ||||
|         do: Routes.container_index_path(Endpoint, :index), | ||||
|         else: Routes.container_index_path(Endpoint, :table) | ||||
|  | ||||
|     {:noreply, socket |> assign(view_table: !view_table) |> push_patch(to: new_path)} | ||||
|   end | ||||
|  | ||||
|   defp display_containers(%{assigns: %{current_user: current_user}} = socket) do | ||||
|     containers = | ||||
|       Containers.list_containers(current_user) |> Repo.preload([:tags, :ammo_groups], force: true) | ||||
|  | ||||
|     socket |> assign(containers: containers) | ||||
|     columns = | ||||
|       [ | ||||
|         %{label: gettext("Name"), key: :name, type: :string}, | ||||
|         %{label: gettext("Description"), key: :desc, type: :string}, | ||||
|         %{label: gettext("Location"), key: :location, type: :string}, | ||||
|         %{label: gettext("Type"), key: :type, type: :string}, | ||||
|         %{label: gettext("Packs"), key: :packs, type: :integer}, | ||||
|         %{label: gettext("Rounds"), key: :rounds, type: :string}, | ||||
|         %{label: gettext("Tags"), key: :tags, type: :tags}, | ||||
|         %{label: nil, key: :actions, sortable: false, type: :actions} | ||||
|       ] | ||||
|       |> Enum.filter(fn %{key: key, type: type} -> | ||||
|         # remove columns if all values match defaults | ||||
|         default_value = | ||||
|           case type do | ||||
|             :boolean -> false | ||||
|             _other_type -> nil | ||||
|           end | ||||
|  | ||||
|         containers | ||||
|         |> Enum.any?(fn container -> | ||||
|           type in [:tags, :actions] or not (container |> Map.get(key) == default_value) | ||||
|         end) | ||||
|       end) | ||||
|  | ||||
|     rows = | ||||
|       containers | ||||
|       |> Enum.map(fn container -> container |> get_row_data_for_container(columns) end) | ||||
|  | ||||
|     socket | ||||
|     |> assign( | ||||
|       containers: containers, | ||||
|       columns: columns, | ||||
|       rows: rows | ||||
|     ) | ||||
|   end | ||||
|  | ||||
|   @spec get_row_data_for_container(Container.t(), [map()]) :: [map()] | ||||
|   defp get_row_data_for_container(container, columns) do | ||||
|     container = container |> Repo.preload([:ammo_groups, :tags]) | ||||
|  | ||||
|     columns | ||||
|     |> Enum.into(%{}, fn %{key: key} -> {key, get_value_for_key(key, container)} end) | ||||
|   end | ||||
|  | ||||
|   @spec get_value_for_key(atom(), Container.t()) :: any() | ||||
|   defp get_value_for_key(:packs, container) do | ||||
|     container |> Containers.get_container_ammo_group_count!() | ||||
|   end | ||||
|  | ||||
|   defp get_value_for_key(:rounds, container) do | ||||
|     container |> Containers.get_container_rounds!() | ||||
|   end | ||||
|  | ||||
|   defp get_value_for_key(:tags, container) do | ||||
|     assigns = %{container: container} | ||||
|  | ||||
|     {container.tags |> Enum.map(fn %{name: name} -> name end), | ||||
|      ~H""" | ||||
|      <div class="flex flex-wrap justify-center items-center"> | ||||
|        <%= unless @container.tags |> Enum.empty?() do %> | ||||
|          <%= for tag <- @container.tags do %> | ||||
|            <TagCard.simple_tag_card tag={tag} /> | ||||
|          <% end %> | ||||
|        <% end %> | ||||
|  | ||||
|        <div class="mx-4 my-2"> | ||||
|          <.link | ||||
|            patch={Routes.container_index_path(Endpoint, :edit_tags, @container)} | ||||
|            class="text-primary-600 link" | ||||
|          > | ||||
|            <i class="fa-fw fa-lg fas fa-tags"></i> | ||||
|          </.link> | ||||
|        </div> | ||||
|      </div> | ||||
|      """} | ||||
|   end | ||||
|  | ||||
|   defp get_value_for_key(:actions, container) do | ||||
|     assigns = %{container: container} | ||||
|  | ||||
|     ~H""" | ||||
|     <.link | ||||
|       patch={Routes.container_index_path(Endpoint, :edit, @container)} | ||||
|       class="text-primary-600 link" | ||||
|       data-qa={"edit-#{@container.id}"} | ||||
|     > | ||||
|       <i class="fa-fw fa-lg fas fa-edit"></i> | ||||
|     </.link> | ||||
|  | ||||
|     <.link | ||||
|       href="#" | ||||
|       class="text-primary-600 link" | ||||
|       phx-click="delete" | ||||
|       phx-value-id={@container.id} | ||||
|       data-confirm={ | ||||
|         dgettext("prompts", "Are you sure you want to delete %{name}?", name: @container.name) | ||||
|       } | ||||
|       data-qa={"delete-#{@container.id}"} | ||||
|     > | ||||
|       <i class="fa-fw fa-lg fas fa-trash"></i> | ||||
|     </.link> | ||||
|     """ | ||||
|   end | ||||
|  | ||||
|   defp get_value_for_key(key, container), do: container |> Map.get(key) | ||||
|  | ||||
|   def return_to(true = _view_table), do: Routes.container_index_path(Endpoint, :table) | ||||
|   def return_to(false = _view_table), do: Routes.container_index_path(Endpoint, :index) | ||||
| end | ||||
|   | ||||
| @@ -16,62 +16,80 @@ | ||||
|     <.link patch={Routes.container_index_path(Endpoint, :new)} class="btn btn-primary"> | ||||
|       <%= dgettext("actions", "New Container") %> | ||||
|     </.link> | ||||
|  | ||||
|     <div class="flex flex-col justify-center items-center"> | ||||
|       <.toggle_button action="toggle_table" value={@view_table}> | ||||
|         <span class="title text-lg text-primary-600"> | ||||
|           <%= gettext("View as table") %> | ||||
|         </span> | ||||
|       </.toggle_button> | ||||
|     </div> | ||||
|   <% end %> | ||||
|  | ||||
|   <div class="max-w-full flex flex-row flex-wrap justify-center items-center"> | ||||
|     <%= for container <- @containers do %> | ||||
|       <.container_card container={container}> | ||||
|         <:tag_actions> | ||||
|           <div class="mx-4 my-2"> | ||||
|             <.link | ||||
|               patch={Routes.container_index_path(Endpoint, :edit_tags, container)} | ||||
|               class="text-primary-600 link" | ||||
|             > | ||||
|               <i class="fa-fw fa-lg fas fa-tags"></i> | ||||
|             </.link> | ||||
|           </div> | ||||
|         </:tag_actions> | ||||
|         <.link | ||||
|           patch={Routes.container_index_path(Endpoint, :edit, container)} | ||||
|           class="text-primary-600 link" | ||||
|           data-qa={"edit-#{container.id}"} | ||||
|         > | ||||
|           <i class="fa-fw fa-lg fas fa-edit"></i> | ||||
|         </.link> | ||||
|     <%= if @view_table do %> | ||||
|       <.live_component | ||||
|         module={CanneryWeb.Components.TableComponent} | ||||
|         id="containers_index_table" | ||||
|         action={@live_action} | ||||
|         columns={@columns} | ||||
|         rows={@rows} | ||||
|       /> | ||||
|     <% else %> | ||||
|       <%= for container <- @containers do %> | ||||
|         <.container_card container={container}> | ||||
|           <:tag_actions> | ||||
|             <div class="mx-4 my-2"> | ||||
|               <.link | ||||
|                 patch={Routes.container_index_path(Endpoint, :edit_tags, container)} | ||||
|                 class="text-primary-600 link" | ||||
|               > | ||||
|                 <i class="fa-fw fa-lg fas fa-tags"></i> | ||||
|               </.link> | ||||
|             </div> | ||||
|           </:tag_actions> | ||||
|           <.link | ||||
|             patch={Routes.container_index_path(Endpoint, :edit, container)} | ||||
|             class="text-primary-600 link" | ||||
|             data-qa={"edit-#{container.id}"} | ||||
|           > | ||||
|             <i class="fa-fw fa-lg fas fa-edit"></i> | ||||
|           </.link> | ||||
|  | ||||
|         <.link | ||||
|           href="#" | ||||
|           class="text-primary-600 link" | ||||
|           phx-click="delete" | ||||
|           phx-value-id={container.id} | ||||
|           data-confirm={ | ||||
|             dgettext("prompts", "Are you sure you want to delete %{name}?", name: container.name) | ||||
|           } | ||||
|           data-qa={"delete-#{container.id}"} | ||||
|         > | ||||
|           <i class="fa-fw fa-lg fas fa-trash"></i> | ||||
|         </.link> | ||||
|       </.container_card> | ||||
|           <.link | ||||
|             href="#" | ||||
|             class="text-primary-600 link" | ||||
|             phx-click="delete" | ||||
|             phx-value-id={container.id} | ||||
|             data-confirm={ | ||||
|               dgettext("prompts", "Are you sure you want to delete %{name}?", name: container.name) | ||||
|             } | ||||
|             data-qa={"delete-#{container.id}"} | ||||
|           > | ||||
|             <i class="fa-fw fa-lg fas fa-trash"></i> | ||||
|           </.link> | ||||
|         </.container_card> | ||||
|       <% end %> | ||||
|     <% end %> | ||||
|   </div> | ||||
| </div> | ||||
|  | ||||
| <%= if @live_action in [:new, :edit] do %> | ||||
|   <.modal return_to={Routes.container_index_path(Endpoint, :index)}> | ||||
|   <.modal return_to={return_to(@view_table)}> | ||||
|     <.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)} | ||||
|       return_to={return_to(@view_table)} | ||||
|       current_user={@current_user} | ||||
|     /> | ||||
|   </.modal> | ||||
| <% end %> | ||||
|  | ||||
| <%= if @live_action == :edit_tags do %> | ||||
|   <.modal return_to={Routes.container_index_path(Endpoint, :index)}> | ||||
|   <.modal return_to={return_to(@view_table)}> | ||||
|     <.live_component | ||||
|       module={CanneryWeb.ContainerLive.EditTagsComponent} | ||||
|       id={@container.id} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user