Packages

A collection of utilities and helpers for Phoenix and Elixir projects.

Current section

9 Versions

Jump to

Compare versions

7 files changed
+108 additions
-79 deletions
  @@ -1,6 +1,6 @@
1 1 {<<"links">>,[{<<"GitHub">>,<<"https://github.com/oscar345/phutilx">>}]}.
2 2 {<<"name">>,<<"phutilx">>}.
3 - {<<"version">>,<<"0.1.0">>}.
3 + {<<"version">>,<<"0.1.1">>}.
4 4 {<<"description">>,
5 5 <<"A collection of utilities and helpers for Phoenix and Elixir projects.">>}.
6 6 {<<"elixir">>,<<"~> 1.18">>}.
  @@ -30,6 +30,6 @@
30 30 {<<"files">>,
31 31 [<<"lib">>,<<"lib/database">>,<<"lib/database/paginate.ex">>,
32 32 <<"lib/phutilx.ex">>,<<"lib/inertia">>,<<"lib/inertia/controller.ex">>,
33 - <<"lib/inertia/form.ex">>,<<"lib/json.ex">>,<<".formatter.exs">>,
33 + <<"lib/inertia/errors.ex">>,<<"lib/json.ex">>,<<".formatter.exs">>,
34 34 <<"mix.exs">>,<<"README.md">>]}.
35 35 {<<"build_tools">>,[<<"mix">>]}.
  @@ -1,15 +1,30 @@
1 1 defmodule Phutilx.Inertia.Controller do
2 2 alias Plug.Conn
3 3
4 + @doc """
5 + Assign a title to both the normal assigns from plug and to the inertia prop assigns so the title
6 + can be used on the server and on the client.
7 + """
4 8 def assign_title(conn, title) do
5 9 conn
6 10 |> Conn.assign(:page_title, title)
7 11 |> Inertia.Controller.assign_prop(:page_title, title)
8 12 end
9 13
10 - def assign_meta(conn, map) do
14 + @doc """
15 + Assign metadata to both the normal assigns from plug and to the inertia prop assigns so the metadata
16 + can be used on the server and on the client.
17 +
18 + The maps parameter should be a list containing maps with the keys `:name` and `:content`.
19 +
20 + ## Examples
21 +
22 + iex> assign_meta(conn, [%{name: "description", content: "A description of the page"}, %{name: "keywords", content: "elixir, phoenix, inertia"}])
23 + %Plug.Conn{...}
24 + """
25 + def assign_meta(conn, maps) do
11 26 conn
12 - |> Conn.assign(:meta, map)
13 - |> Inertia.Controller.assign_prop(:meta, map)
27 + |> Conn.assign(:meta, maps)
28 + |> Inertia.Controller.assign_prop(:meta, maps)
14 29 end
15 30 end
  @@ -0,0 +1,84 @@
1 + defmodule Phutilx.Inertia.Errors do
2 + @moduledoc """
3 + A module to help with sending validation errors to the client when using Inertia.js. You can prepend keys
4 + to the errors when you have all your data underneath a key on the client. For example when you have a form
5 + for a user, you might want to have all the fields and errors under the `user` key.
6 +
7 + It also makes the experience for returning errors from maps equivalent to returning errors from changesets. So
8 + those errors are also flattened and can be prefixed with a key.
9 +
10 + In order to translate the error messages, you need to set the `:gettext_module` configuration option in your
11 + `config/config.exs` file. For example: `config :phutilx, :gettext_module, MyAppWeb.Gettext`.
12 + """
13 +
14 + defstruct key: nil, changeset: nil, map: nil
15 +
16 + @type t :: %__MODULE__{
17 + key: atom() | nil,
18 + changeset: Ecto.Changeset.t() | nil,
19 + map: map() | nil
20 + }
21 +
22 + def from_changeset(%Ecto.Changeset{} = changeset, key \\ nil) do
23 + %__MODULE__{key: key, changeset: changeset}
24 + end
25 +
26 + def from_map(map, key \\ nil) when is_map(map) do
27 + %__MODULE__{key: key, map: map}
28 + end
29 +
30 + defimpl Inertia.Errors do
31 + alias Ecto.Changeset
32 +
33 + @gettext_module Application.compile_env(:phutilx, :gettext_module)
34 +
35 + def to_errors(%Phutilx.Inertia.Errors{changeset: %Changeset{} = changeset} = value, fun) do
36 + errors =
37 + if fun != nil do
38 + Inertia.Errors.to_errors(changeset, fun)
39 + else
40 + Inertia.Errors.to_errors(changeset)
41 + end
42 +
43 + if value.key == nil do
44 + errors
45 + else
46 + # Prefix the keys with the form's key
47 + errors |> Enum.map(fn {k, v} -> {"#{value.key}.#{k}", v} end) |> Map.new()
48 + end
49 + end
50 +
51 + def to_errors(%Phutilx.Inertia.Errors{changeset: %Changeset{}} = value) do
52 + to_errors(value, fn {msg, opts} ->
53 + if count = opts[:count] do
54 + Gettext.dngettext(@gettext_module, "errors", msg, msg, count, opts)
55 + else
56 + Gettext.dgettext(@gettext_module, "errors", msg, opts)
57 + end
58 + end)
59 + end
60 +
61 + def to_errors(%Phutilx.Inertia.Errors{map: %{} = map} = value) do
62 + errors = flatten_map(map)
63 +
64 + if value.key == nil do
65 + errors
66 + else
67 + # Prefix the keys with the form's key
68 + errors |> Enum.map(fn {k, v} -> {"#{value.key}.#{k}", v} end) |> Map.new()
69 + end
70 + end
71 +
72 + defp flatten_map(map, parent_key \\ nil, acc \\ %{}) do
73 + Enum.reduce(map, acc, fn {k, v}, acc ->
74 + key = if parent_key, do: "#{parent_key}.#{k}", else: to_string(k)
75 +
76 + if is_map(v) do
77 + flatten_map(v, key, acc)
78 + else
79 + Map.put(acc, key, v)
80 + end
81 + end)
82 + end
83 + end
84 + end
  @@ -1,72 +0,0 @@
1 - defmodule Phutilx.Inertia.Form do
2 - defstruct key: nil, changeset: nil, map: nil
3 -
4 - @type t :: %__MODULE__{
5 - key: atom() | nil,
6 - changeset: Ecto.Changeset.t() | nil,
7 - map: map() | nil
8 - }
9 -
10 - def from_changeset(%Ecto.Changeset{} = changeset, key \\ nil) do
11 - %__MODULE__{key: key, changeset: changeset}
12 - end
13 -
14 - def from_map(map, key \\ nil) when is_map(map) do
15 - %__MODULE__{key: key, map: map}
16 - end
17 -
18 - defimpl Inertia.Errors do
19 - alias Ecto.Changeset
20 -
21 - @gettext_module Application.compile_env(:phutilx, :gettext_module)
22 -
23 - def to_errors(%Phutilx.Inertia.Form{changeset: %Changeset{} = changeset} = value, fun) do
24 - errors =
25 - if fun != nil do
26 - Inertia.Errors.to_errors(changeset, fun)
27 - else
28 - Inertia.Errors.to_errors(changeset)
29 - end
30 -
31 - if value.key == nil do
32 - errors
33 - else
34 - # Prefix the keys with the form's key
35 - errors |> Enum.map(fn {k, v} -> {"#{value.key}.#{k}", v} end) |> Map.new()
36 - end
37 - end
38 -
39 - def to_errors(%Phutilx.Inertia.Form{changeset: %Changeset{}} = value) do
40 - to_errors(value, fn {msg, opts} ->
41 - if count = opts[:count] do
42 - Gettext.dngettext(@gettext_module, "errors", msg, msg, count, opts)
43 - else
44 - Gettext.dgettext(@gettext_module, "errors", msg, opts)
45 - end
46 - end)
47 - end
48 -
49 - def to_errors(%Phutilx.Inertia.Form{map: %{} = map} = value) do
50 - errors = flatten_map(map)
51 -
52 - if value.key == nil do
53 - errors
54 - else
55 - # Prefix the keys with the form's key
56 - errors |> Enum.map(fn {k, v} -> {"#{value.key}.#{k}", v} end) |> Map.new()
57 - end
58 - end
59 -
60 - defp flatten_map(map, parent_key \\ nil, acc \\ %{}) do
61 - Enum.reduce(map, acc, fn {k, v}, acc ->
62 - key = if parent_key, do: "#{parent_key}.#{k}", else: to_string(k)
63 -
64 - if is_map(v) do
65 - flatten_map(v, key, acc)
66 - else
67 - Map.put(acc, key, v)
68 - end
69 - end)
70 - end
71 - end
72 - end
  @@ -10,7 +10,6 @@ defmodule Phutilx.JSON do
10 10 * `:except` - A list of fields to exclude from the JSON output. This option is ignored if `:only`
11 11 is provided. `:__struct__` and `:__meta__` are always excluded.
12 12 """
13 -
14 13 defmacro encoder(opts \\ []) do
15 14 quote do
16 15 defimpl JSON.Encoder do
Loading more files…