Skip to content

Commit

Permalink
Fix bug with multiple filters w/ the same prefix
Browse files Browse the repository at this point in the history
* See GitHub Issue 242: #242

[close #242]
  • Loading branch information
cpjolicoeur committed Jun 22, 2021
1 parent 084dc77 commit da32140
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 14 deletions.
64 changes: 51 additions & 13 deletions lib/torch/views/filter_view.ex
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ defmodule Torch.FilterView do
@spec filter_select(prefix, field, map) :: Phoenix.HTML.safe()
def filter_select(prefix, field, params) do
prefix_str = to_string(prefix)
{selected, _value} = find_param(params[prefix_str], field)
{selected, _value} = find_param(params[prefix_str], field, :select)

opts = [
{message("Contains"), "#{prefix}[#{field}_contains]"},
Expand All @@ -67,7 +67,7 @@ defmodule Torch.FilterView do
@spec filter_date_select(prefix, field, map) :: Phoenix.HTML.safe()
def filter_date_select(prefix, field, params) do
prefix_str = to_string(prefix)
{selected, _value} = find_param(params[prefix_str], field)
{selected, _value} = find_param(params[prefix_str], field, :date_select)

opts = [
{message("Before"), "#{prefix}[#{field}_before]"},
Expand All @@ -89,7 +89,7 @@ defmodule Torch.FilterView do
@spec number_filter_select(prefix, field, map) :: Phoenix.HTML.safe()
def number_filter_select(prefix, field, params) do
prefix_str = to_string(prefix)
{selected, _value} = find_param(params[prefix_str], field)
{selected, _value} = find_param(params[prefix_str], field, :number_select)

opts = [
{message("Equals"), "#{prefix}[#{field}_equals]"},
Expand Down Expand Up @@ -189,7 +189,7 @@ defmodule Torch.FilterView do

def filter_date_input(prefix, field, params, :select) do
prefix_str = to_string(prefix)
{name, value} = find_param(params[prefix_str], field, :date)
{name, value} = find_param(params[prefix_str], field, :date_select)

{:safe, date_input} =
torch_date_input(
Expand Down Expand Up @@ -257,19 +257,57 @@ defmodule Torch.FilterView do
tag(:input, type: "text", class: "datepicker #{class}", name: name, value: value)
end

defp find_param(params, pattern, type \\ :string) do
pattern = to_string(pattern)
defp find_param(params, field, type \\ :string)

defp find_param(params, field, :string) do
do_find_param(params, field, "contains")
end

defp find_param(params, field, :number) do
do_find_param(params, field, "equals")
end

defp find_param(params, field, :select) do
do_find_param(params, field, ~w(equals contains))
end

defp find_param(params, field, :date_select) do
do_find_param(params, field, ~w(before after))
end

defp find_param(params, field, :number_select) do
do_find_param(params, field, ~w(equals greater_than greater_than_or less_than))
end

defp do_find_param(params, field, comparison) when is_binary(comparison) do
field = to_string(field)

result =
Enum.find(params || %{}, fn {param_name, _val} ->
param_name == "#{field}_#{comparison}"
end)

if is_nil(result) do
{"#{field}_#{comparison}", nil}
else
result
end
end

defp do_find_param(params, field, suffixes) when is_list(suffixes) do
field = to_string(field)
suffix_patterns = Enum.join(suffixes, "|")
default = List.first(suffixes)

result =
Enum.find(params || %{}, fn {key, _val} ->
String.starts_with?(key, pattern)
Enum.find(params || %{}, fn {param_name, _val} ->
String.match?(param_name, ~r/#{field}_[#{suffix_patterns}]/)
end)

cond do
result == nil && type == :string -> {"#{pattern}_contains", nil}
result == nil && type == :number -> {"#{pattern}_equals", nil}
result == nil && type == :date -> {"#{pattern}_before", nil}
result != nil -> result
if is_nil(result) do
{"#{field}_#{default}", nil}
else
result
end
end
end
23 changes: 22 additions & 1 deletion test/torch/views/filter_view_test.exs
Original file line number Diff line number Diff line change
@@ -1,7 +1,28 @@
defmodule Torch.FilterViewTest do
use ExUnit.Case
use ExUnit.Case, async: true

import Phoenix.HTML, only: [safe_to_string: 1]

doctest Torch.FilterView, import: true

test "param name prefixes do not collide" do
# * See GitHub Issue 242: https://github.com/mojotech/torch/issues/242

params = %{
"filters" => [
"user[email_contains]",
"user[first_name_contains]",
"user[last_name_contains]",
"user[id_equals]"
],
"user" => %{
"email_confirmed_at_between" => %{"end" => "2021-06-03", "start" => "2021-06-08"}
}
}

expected = "<input id=\"user_email_contains\" name=\"user[email_contains]\" type=\"text\">"

assert expected ==
safe_to_string(Torch.FilterView.filter_string_input(:user, :email, params))
end
end

0 comments on commit da32140

Please sign in to comment.