defmodule ForageWeb.ForageView do @moduledoc """ Helper functions for veiws that feature forage filters, pagination buttons or sort links. """ import Phoenix.HTML, only: [sigil_e: 2] import Phoenix.HTML.Link, only: [link: 2] import Phoenix.HTML.Form, only: [input_value: 2, form_for: 4, select: 4] alias Phoenix.HTML.FormData alias ForageWeb.Naming defmacro __using__(options) do routes_module = case Keyword.fetch(options, :routes_module) do {:ok, module} -> module :error -> raise ArgumentError, "Requires a `:routes_module`." end prefix = case Keyword.fetch(options, :prefix) do {:ok, val} -> val :error -> raise ArgumentError, "Requires a `:prefix`." end resource_path_fun_name = String.to_atom("#{prefix}_path") pagination_widget_fun_name = String.to_atom("#{prefix}_pagination_widget") sort_link_fun_name = String.to_atom("#{prefix}_sort_link") search_form_for_fun_name = String.to_atom("#{prefix}_search_form_for") quote do import ForageWeb.ForageView def unquote(search_form_for_fun_name)(conn, options \\ [], fun) do action = unquote(routes_module).unquote(resource_path_fun_name)(conn, :index) forage_search_form_for( conn, action, options, fun ) end def unquote(sort_link_fun_name)(conn, field, content, options \\ []) do forage_sort_link( conn, unquote(routes_module), unquote(resource_path_fun_name), field, content, options ) end def unquote(pagination_widget_fun_name)(conn, resource, options \\ []) do forage_pagination_widget( conn, resource, unquote(routes_module), unquote(resource_path_fun_name), options ) end end end def forage_select(form, field, opts) do # Params path = Keyword.fetch!(opts, :path) display = Keyword.fetch!(opts, :display) remote_field = Keyword.fetch!(opts, :remote_field) # Derived values field_value = Map.get(form.data, field) ~e""" """ end def forage_select_filter(form, field, opts) do # Params path = Keyword.fetch!(opts, :path) display = Keyword.fetch!(opts, :display) remote_field = Keyword.fetch!(opts, :remote_field) # Derived values IO.inspect({form.data, field}) field_value = Map.get(form.data, field) ~e""" """ end @text_operators [ {"Contains", "contains"}, {"Equal to", "equal_to"}, {"Starts with", "starts_with"}, {"Ends with", "ends_with"} ] @number_operators [ {"Equal to", "equal_to"}, {"Greater than", "greater_than"}, {"Less than", "less_than"}, {"Greater than or equal to", "greater_than_or_equal_to"}, {"Less than or equal to", "less_than_or_equal_to"} ] @operator_class "col-sm-3" @value_class "col-sm-9" defp name_to_search_id(name) do ["_search", to_string(name)] end defp sort_direction(conn, field) do direction_string = get_in(conn.params, ["_sort", to_string(field), "direction"]) case direction_string do "asc" -> :asc "desc" -> :desc nil -> nil end end defp sort_by(conn, field, direction) do conn.params # Remove the old pagination data, which is useless now |> Map.delete("_pagination") |> Map.put("_sort", %{field => %{"direction" => direction}}) end def forage_sort_link(conn, mod, fun, field, content, options \\ []) do icon_down = Keyword.get(options, :icon_down, " ↓") icon_up = Keyword.get(options, :icon_up, " ↑") {link_content, new_conn_params} = case sort_direction(conn, field) do :asc -> {[content, " ", icon_down], sort_by(conn, field, "desc")} :desc -> {[content, " ", icon_up], sort_by(conn, field, "asc")} nil -> {content, sort_by(conn, field, "desc")} end destination = apply(mod, fun, [conn, :index, new_conn_params]) link(link_content, to: destination) end def forage_pagination_link_previous(conn, resource, mod, fun, contents) do if resource.metadata.before do before_params = Map.put(conn.params, :_pagination, %{before: resource.metadata.before}) destination = apply(mod, fun, [conn, :index, before_params]) ~e'