forked from shibao/cannery
		
	add search to range index
This commit is contained in:
		@@ -15,10 +15,50 @@ defmodule Cannery.ActivityLog do
 | 
			
		||||
      iex> list_shot_groups(%User{id: 123})
 | 
			
		||||
      [%ShotGroup{}, ...]
 | 
			
		||||
 | 
			
		||||
      iex> list_shot_groups("cool", %User{id: 123})
 | 
			
		||||
      [%ShotGroup{notes: "My cool shot group"}, ...]
 | 
			
		||||
 | 
			
		||||
  """
 | 
			
		||||
  @spec list_shot_groups(User.t()) :: [ShotGroup.t()]
 | 
			
		||||
  def list_shot_groups(%User{id: user_id}) do
 | 
			
		||||
    Repo.all(from(sg in ShotGroup, where: sg.user_id == ^user_id))
 | 
			
		||||
  @spec list_shot_groups(search :: nil | String.t(), User.t()) :: [ShotGroup.t()]
 | 
			
		||||
  def list_shot_groups(search \\ nil, user)
 | 
			
		||||
 | 
			
		||||
  def list_shot_groups(search, %{id: user_id}) when search |> is_nil() or search == "",
 | 
			
		||||
    do: Repo.all(from sg in ShotGroup, where: sg.user_id == ^user_id)
 | 
			
		||||
 | 
			
		||||
  def list_shot_groups(search, %{id: user_id}) when search |> is_binary() do
 | 
			
		||||
    trimmed_search = String.trim(search)
 | 
			
		||||
 | 
			
		||||
    Repo.all(
 | 
			
		||||
      from sg in ShotGroup,
 | 
			
		||||
        left_join: ag in assoc(sg, :ammo_group),
 | 
			
		||||
        left_join: at in assoc(ag, :ammo_type),
 | 
			
		||||
        where: sg.user_id == ^user_id,
 | 
			
		||||
        where:
 | 
			
		||||
          fragment(
 | 
			
		||||
            "? @@ websearch_to_tsquery('english', ?)",
 | 
			
		||||
            sg.search,
 | 
			
		||||
            ^trimmed_search
 | 
			
		||||
          ) or
 | 
			
		||||
            fragment(
 | 
			
		||||
              "? @@ websearch_to_tsquery('english', ?)",
 | 
			
		||||
              ag.search,
 | 
			
		||||
              ^trimmed_search
 | 
			
		||||
            ) or
 | 
			
		||||
            fragment(
 | 
			
		||||
              "? @@ websearch_to_tsquery('english', ?)",
 | 
			
		||||
              at.search,
 | 
			
		||||
              ^trimmed_search
 | 
			
		||||
            ),
 | 
			
		||||
        order_by: {
 | 
			
		||||
          :desc,
 | 
			
		||||
          fragment(
 | 
			
		||||
            "ts_rank_cd(?, websearch_to_tsquery('english', ?), 4)",
 | 
			
		||||
            sg.search,
 | 
			
		||||
            ^trimmed_search
 | 
			
		||||
          )
 | 
			
		||||
        }
 | 
			
		||||
    )
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  @doc """
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,13 @@ defmodule CanneryWeb.RangeLive.Index do
 | 
			
		||||
  alias Phoenix.LiveView.Socket
 | 
			
		||||
 | 
			
		||||
  @impl true
 | 
			
		||||
  def mount(_params, _session, socket), do: {:ok, socket |> display_shot_groups()}
 | 
			
		||||
  def mount(%{"search" => search}, _session, socket) do
 | 
			
		||||
    {:ok, socket |> assign(search: search) |> display_shot_groups()}
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def mount(_params, _session, socket) do
 | 
			
		||||
    {:ok, socket |> assign(search: nil) |> display_shot_groups()}
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  @impl true
 | 
			
		||||
  def handle_params(params, _url, %{assigns: %{live_action: live_action}} = socket) do
 | 
			
		||||
@@ -23,26 +29,46 @@ defmodule CanneryWeb.RangeLive.Index do
 | 
			
		||||
         %{"id" => id}
 | 
			
		||||
       ) do
 | 
			
		||||
    socket
 | 
			
		||||
    |> assign(:page_title, gettext("Record Shots"))
 | 
			
		||||
    |> assign(:ammo_group, Ammo.get_ammo_group!(id, current_user))
 | 
			
		||||
    |> assign(
 | 
			
		||||
      page_title: gettext("Record Shots"),
 | 
			
		||||
      ammo_group: Ammo.get_ammo_group!(id, current_user)
 | 
			
		||||
    )
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  defp apply_action(%{assigns: %{current_user: current_user}} = socket, :edit, %{"id" => id}) do
 | 
			
		||||
    socket
 | 
			
		||||
    |> assign(:page_title, gettext("Edit Shot Records"))
 | 
			
		||||
    |> assign(:shot_group, ActivityLog.get_shot_group!(id, current_user))
 | 
			
		||||
    |> assign(
 | 
			
		||||
      page_title: gettext("Edit Shot Records"),
 | 
			
		||||
      shot_group: ActivityLog.get_shot_group!(id, current_user)
 | 
			
		||||
    )
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  defp apply_action(socket, :new, _params) do
 | 
			
		||||
    socket
 | 
			
		||||
    |> assign(:page_title, gettext("New Shot Records"))
 | 
			
		||||
    |> assign(:shot_group, %ShotGroup{})
 | 
			
		||||
    |> assign(
 | 
			
		||||
      page_title: gettext("New Shot Records"),
 | 
			
		||||
      shot_group: %ShotGroup{}
 | 
			
		||||
    )
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  defp apply_action(socket, :index, _params) do
 | 
			
		||||
    socket
 | 
			
		||||
    |> assign(:page_title, gettext("Shot Records"))
 | 
			
		||||
    |> assign(:shot_group, nil)
 | 
			
		||||
    |> assign(
 | 
			
		||||
      page_title: gettext("Shot Records"),
 | 
			
		||||
      search: nil,
 | 
			
		||||
      shot_group: nil
 | 
			
		||||
    )
 | 
			
		||||
    |> display_shot_groups()
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  defp apply_action(socket, :search, %{"search" => search}) do
 | 
			
		||||
    socket
 | 
			
		||||
    |> assign(
 | 
			
		||||
      page_title: gettext("Shot Records"),
 | 
			
		||||
      search: search,
 | 
			
		||||
      shot_group: nil
 | 
			
		||||
    )
 | 
			
		||||
    |> display_shot_groups()
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  @impl true
 | 
			
		||||
@@ -55,6 +81,7 @@ defmodule CanneryWeb.RangeLive.Index do
 | 
			
		||||
    {:noreply, socket |> put_flash(:info, prompt) |> display_shot_groups()}
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  @impl true
 | 
			
		||||
  def handle_event(
 | 
			
		||||
        "toggle_staged",
 | 
			
		||||
        %{"ammo_group_id" => ammo_group_id},
 | 
			
		||||
@@ -69,10 +96,20 @@ defmodule CanneryWeb.RangeLive.Index do
 | 
			
		||||
    {:noreply, socket |> put_flash(:info, prompt) |> display_shot_groups()}
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  @impl true
 | 
			
		||||
  def handle_event("search", %{"search" => %{"search_term" => ""}}, socket) do
 | 
			
		||||
    {:noreply, socket |> push_patch(to: Routes.range_index_path(Endpoint, :index))}
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def handle_event("search", %{"search" => %{"search_term" => search_term}}, socket) do
 | 
			
		||||
    {:noreply, socket |> push_patch(to: Routes.range_index_path(Endpoint, :search, search_term))}
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  @spec display_shot_groups(Socket.t()) :: Socket.t()
 | 
			
		||||
  defp display_shot_groups(%{assigns: %{current_user: current_user}} = socket) do
 | 
			
		||||
  defp display_shot_groups(%{assigns: %{search: search, current_user: current_user}} = socket) do
 | 
			
		||||
    shot_groups =
 | 
			
		||||
      ActivityLog.list_shot_groups(current_user) |> Repo.preload(ammo_group: :ammo_type)
 | 
			
		||||
      ActivityLog.list_shot_groups(search, current_user)
 | 
			
		||||
      |> Repo.preload(ammo_group: :ammo_type)
 | 
			
		||||
 | 
			
		||||
    ammo_groups = Ammo.list_staged_ammo_groups(current_user)
 | 
			
		||||
 | 
			
		||||
@@ -114,7 +151,7 @@ defmodule CanneryWeb.RangeLive.Index do
 | 
			
		||||
        label: gettext("Rounds shot: %{count}", count: sum)
 | 
			
		||||
      }
 | 
			
		||||
    end)
 | 
			
		||||
    |> Enum.sort_by(fn %{date: date} -> date end)
 | 
			
		||||
    |> Enum.sort_by(fn %{date: date} -> date end, Date)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  @spec get_row_data_for_shot_group(ShotGroup.t(), [map()]) :: map()
 | 
			
		||||
 
 | 
			
		||||
@@ -43,7 +43,7 @@
 | 
			
		||||
 | 
			
		||||
  <hr class="hr" />
 | 
			
		||||
 | 
			
		||||
  <%= if @shot_groups |> Enum.empty?() do %>
 | 
			
		||||
  <%= if @shot_groups |> Enum.empty?() and @search |> is_nil() do %>
 | 
			
		||||
    <h1 class="title text-xl text-primary-600">
 | 
			
		||||
      <%= gettext("No shots recorded") %>
 | 
			
		||||
      <%= display_emoji("😔") %>
 | 
			
		||||
@@ -67,14 +67,39 @@
 | 
			
		||||
      <%= dgettext("errors", "Your browser does not support the canvas element.") %>
 | 
			
		||||
    </canvas>
 | 
			
		||||
 | 
			
		||||
    <.live_component
 | 
			
		||||
      module={CanneryWeb.Components.TableComponent}
 | 
			
		||||
      id="shot_groups_index_table"
 | 
			
		||||
      columns={@columns}
 | 
			
		||||
      rows={@rows}
 | 
			
		||||
      initial_key={:date}
 | 
			
		||||
      initial_sort_mode={:desc}
 | 
			
		||||
    />
 | 
			
		||||
    <div class="w-full flex flex-col sm:flex-row justify-center items-center space-y-4 sm:space-y-0 sm:space-x-4 max-w-xl">
 | 
			
		||||
      <.form
 | 
			
		||||
        :let={f}
 | 
			
		||||
        for={:search}
 | 
			
		||||
        phx-change="search"
 | 
			
		||||
        phx-submit="search"
 | 
			
		||||
        class="grow self-stretch flex flex-col items-stretch"
 | 
			
		||||
        data-qa="shot_group_search"
 | 
			
		||||
      >
 | 
			
		||||
        <%= text_input(f, :search_term,
 | 
			
		||||
          class: "input input-primary",
 | 
			
		||||
          value: @search,
 | 
			
		||||
          phx_debounce: 300,
 | 
			
		||||
          placeholder: gettext("Search shot records")
 | 
			
		||||
        ) %>
 | 
			
		||||
      </.form>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <%= if @shot_groups |> Enum.empty?() do %>
 | 
			
		||||
      <h1 class="title text-xl text-primary-600">
 | 
			
		||||
        <%= gettext("No shots recorded") %>
 | 
			
		||||
        <%= display_emoji("😔") %>
 | 
			
		||||
      </h1>
 | 
			
		||||
    <% else %>
 | 
			
		||||
      <.live_component
 | 
			
		||||
        module={CanneryWeb.Components.TableComponent}
 | 
			
		||||
        id="shot_groups_index_table"
 | 
			
		||||
        columns={@columns}
 | 
			
		||||
        rows={@rows}
 | 
			
		||||
        initial_key={:date}
 | 
			
		||||
        initial_sort_mode={:desc}
 | 
			
		||||
      />
 | 
			
		||||
    <% end %>
 | 
			
		||||
  <% end %>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -103,8 +103,9 @@ defmodule CanneryWeb.Router do
 | 
			
		||||
    live "/ammo/show/:id/edit/:shot_group_id", AmmoGroupLive.Show, :edit_shot_group
 | 
			
		||||
 | 
			
		||||
    live "/range", RangeLive.Index, :index
 | 
			
		||||
    live "/range/:id/edit", RangeLive.Index, :edit
 | 
			
		||||
    live "/range/:id/add_shot_group", RangeLive.Index, :add_shot_group
 | 
			
		||||
    live "/range/edit/:id", RangeLive.Index, :edit
 | 
			
		||||
    live "/range/add_shot_group/:id", RangeLive.Index, :add_shot_group
 | 
			
		||||
    live "/range/search/:search", RangeLive.Index, :search
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  scope "/", CanneryWeb do
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user