Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixes #89 #91 added ability for has_many forms to insert collection w… #363

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 51 additions & 8 deletions lib/ex_admin/themes/active_admin/form.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ defmodule ExAdmin.Theme.ActiveAdmin.Form do
import ExAdmin.Helpers
import ExAdmin.Gettext
alias ExAdmin.Schema
import ExAdmin.Form.Fields, only: [input_collection: 9]

@doc false
def build_form(conn, resource, items, params, script_block, global_script) do
Expand Down Expand Up @@ -216,16 +217,17 @@ defmodule ExAdmin.Theme.ActiveAdmin.Form do
text humanize(f_name)
required_abbr required
end
select "##{ext_name}_#{f_name}", [name: name ] do
for opt <- collection do
if not is_nil(res) and (Map.get(res, f_name) == opt) do
option "#{opt}", [value: escape_value(opt), selected: :selected]
else
option "#{opt}", [value: escape_value(opt)]
end

binary_tuple = binary_tuple?(collection)

markup do
if binary_tuple do
build_select_theme_binary_tuple_list(collection, field, field[:name], res, model_name, ext_name)
else
input_collection(res, collection, model_name, field[:name], nil, nil, field, conn.params, error)
end
build_errors(errors, field[:opts][:hint])
end
build_errors(errors, field[:opts][:hint])
end
_ ->
li ".string.input.stringish#{error}", id: "#{ext_name}_#{f_name}_input" do
Expand Down Expand Up @@ -294,4 +296,45 @@ defmodule ExAdmin.Theme.ActiveAdmin.Form do
end
end
end

defp build_select_theme_binary_tuple_list(collection, item, field_name, resource, model_name, ext_name) do
html_opts = item[:opts][:html_opts] || []
html_opts = Keyword.merge([name: "#{model_name}[#{field_name}]"], html_opts)
select "##{ext_name}_#{field_name}", html_opts do
handle_prompt(field_name, item)
for item <- collection do
{value, name} = case item do
{value, name} -> {value, name}
other -> {other, other}
end

selected = if Map.get(resource, field_name) == value,
do: [selected: :selected], else: []
option(name, [value: value] ++ selected)
end
end
end

defp handle_prompt(field_name, item) do
case get_prompt(field_name, item) do
false -> nil
prompt -> option(prompt, value: "")
end
end

defp get_prompt(field_name, item) do
case Map.get item[:opts], :prompt, nil do
nil ->
nm = humanize("#{field_name}")
|> articlize
(gettext "Select %{nm}",nm: nm)
other -> other
end
end

defp binary_tuple?([]), do: false

defp binary_tuple?(collection) do
Enum.all?(collection, &(is_binary(&1) or (is_tuple(&1) and (tuple_size(&1) == 2))))
end
end
62 changes: 52 additions & 10 deletions lib/ex_admin/themes/admin_lte2/form.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ defmodule ExAdmin.Theme.AdminLte2.Form do
import ExAdmin.Helpers
import ExAdmin.Gettext
alias ExAdmin.Schema
import ExAdmin.Form.Fields, only: [input_collection: 9]

@doc false
def build_form(conn, resource, items, params, script_block, global_script) do
Expand Down Expand Up @@ -216,21 +217,21 @@ defmodule ExAdmin.Theme.AdminLte2.Form do
collection = if is_function(collection), do: collection.(conn, res), else: collection
div ".form-group", [id: "#{ext_name}_label_input"] do
label ".col-sm-2.control-label", for: "#{ext_name}_#{f_name}" do
text humanize(f_name)
text humanize(f_name)
required_abbr required
end

binary_tuple = binary_tuple?(collection)

div ".col-sm-10" do
select "##{ext_name}_#{f_name}#{error}.form-control", [name: name ] do
for opt <- collection do
cond do
not is_nil(res) and (Map.get(res, f_name) == opt) ->
option "#{opt}", [value: escape_value(opt), selected: :selected]
true ->
option "#{opt}", [value: escape_value(opt)]
end
markup do
if binary_tuple do
build_select_theme_binary_tuple_list(collection, field, field[:name], res, model_name, ext_name)
else
input_collection(res, collection, model_name, field[:name], nil, nil, field, conn.params, error)
end
build_errors(errors, field[:opts][:hint])
end
build_errors(errors, field[:opts][:hint])
end
end
_ ->
Expand Down Expand Up @@ -312,4 +313,45 @@ defmodule ExAdmin.Theme.AdminLte2.Form do
end
end
end

defp build_select_theme_binary_tuple_list(collection, field, field_name, resource, model_name, ext_name) do
html_opts = field[:opts][:html_opts] || []
html_opts = Keyword.merge([name: "#{model_name}[#{field_name}]"], html_opts)
select("##{ext_name}_id.form-control", html_opts) do
handle_prompt(field_name, field)
for field <- collection do
{value, name} = case field do
{value, name} -> {value, name}
other -> {other, other}
end

selected = if Map.get(resource, field_name) == value,
do: [selected: :selected], else: []
option(name, [value: value] ++ selected)
end
end
end

defp handle_prompt(field_name, field) do
case get_prompt(field_name, field) do
false -> nil
prompt -> option(prompt, value: "")
end
end

defp get_prompt(field_name, field) do
case Map.get field[:opts], :prompt, nil do
nil ->
nm = humanize("#{field_name}")
|> articlize
(gettext "Select %{nm}",nm: nm)
other -> other
end
end

defp binary_tuple?([]), do: false

defp binary_tuple?(collection) do
Enum.all?(collection, &(is_binary(&1) or (is_tuple(&1) and (tuple_size(&1) == 2))))
end
end
3 changes: 3 additions & 0 deletions test/support/schema.exs
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,9 @@ defmodule TestExAdmin.PhoneNumber do
def labels, do: ["Primary Phone", "Secondary Phone", "Home Phone",
"Work Phone", "Mobile Phone", "Other Phone"]

def tuple_labels, do: [{"primary phone", "Primary Phone"}, {"secondary phone", "Secondary Phone"}, {"home phone", "Home Phone"},
{"work phone", "Work Phone"}, {"mobile phone", "Mobile Phone"}, {"other phone", "Other Phone"}]

def all_labels do
(from p in PhoneNumber, group_by: p.label, select: p.label)
|> Repo.all
Expand Down
43 changes: 42 additions & 1 deletion test/themes/form_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ defmodule ExAdmin.ThemeFormTest do

test "AdminLte2 theme_build_has_many_fieldset", %{conn: conn} do
pn = Repo.insert! PhoneNumber.changeset(%PhoneNumber{}, %{label: "Home Phone", number: "5555555555"})

fields = build_fields pn

{inx, html} = AdminLte2.Form.theme_build_has_many_fieldset(conn, pn, fields, 0, "contact_phone_numbers_attributes_0",
Expand All @@ -20,9 +21,24 @@ defmodule ExAdmin.ThemeFormTest do
assert inx == 0

assert Floki.find(html, "div div h3") |> Floki.text == "Phone Number"

end

test "AdminLte2 theme_build_has_many_fieldset with collection tuple", %{conn: conn} do
pn = Repo.insert! PhoneNumber.changeset(%PhoneNumber{}, %{label: "Home Phone", number: "5555555555"})

fields = build_fields_with_tuple pn

{inx, html} = AdminLte2.Form.theme_build_has_many_fieldset(conn, pn, fields, 0, "contact_phone_numbers_attributes_0",
:phone_numbers, "phone_numbers_attributes", "contact", nil)

floki_attributes = Floki.find(html, "div.col-sm-10 select option") |> Floki.attribute("value")

assert inx == 0
assert floki_attributes == ["", "primary phone", "secondary phone", "home phone", "work phone", "mobile phone", "other phone"]
assert Floki.find(html, "div.col-sm-10 select option") |> Floki.text =~ "Secondary Phone"
assert Floki.find(html, "div div h3") |> Floki.text == "Phone Number"
end

test "AdminLte2 theme_build_has_many_fieldset with errors", %{conn: conn} do
pn = %{_destroy: "0", label: "Primary Phone", number: nil}
fields = [%{name: :label,
Expand Down Expand Up @@ -55,7 +71,22 @@ defmodule ExAdmin.ThemeFormTest do

assert Floki.find(html, "fieldset ol h3") |> Floki.text == "Phone Number"
end

test "ActiveAdmin theme_build_has_many_fieldset with collection tuple", %{conn: conn} do
pn = Repo.insert! PhoneNumber.changeset(%PhoneNumber{}, %{label: "Home Phone", number: "5555555555"})

fields = build_fields_with_tuple pn

{inx, html} = ActiveAdmin.Form.theme_build_has_many_fieldset(conn, pn, fields, 0, "contact_phone_numbers_attributes_0",
:phone_numbers, "phone_numbers_attributes", "contact", nil)

floki_attributes = Floki.find(html, "select option") |> Floki.attribute("value")

assert inx == 0
assert floki_attributes == ["", "primary phone", "secondary phone", "home phone", "work phone", "mobile phone", "other phone"]
assert Floki.find(html, "select option") |> Floki.text =~ "Secondary Phone"
assert Floki.find(html, "fieldset ol h3") |> Floki.text == "Phone Number"
end

################
# Helpers
Expand All @@ -69,4 +100,14 @@ defmodule ExAdmin.ThemeFormTest do
%{name: :number, opts: %{}, resource: resource, type: :input}
]
end

defp build_fields_with_tuple(resource) do
[
%{
name: :label, resource: resource, type: :input,
opts: %{collection: PhoneNumber.tuple_labels},
},
%{name: :number, opts: %{}, resource: resource, type: :input}
]
end
end