From baeabae586eb7c1a183426b38ce81cf3e827bdcd Mon Sep 17 00:00:00 2001 From: Esdras Eduardo Date: Wed, 11 Dec 2024 16:25:36 +0800 Subject: [PATCH] feat(Calculations): Able to show calculations --- dev/resources/accounts/calculations/concat.ex | 30 +++ dev/resources/accounts/resources/user.ex | 25 ++- lib/ash_admin/components/core_components.ex | 56 +++--- lib/ash_admin/components/layouts.ex | 4 +- .../components/resource/data_table.ex | 34 ++-- lib/ash_admin/components/resource/form.ex | 113 ++++++----- .../components/resource/generic_action.ex | 24 +-- .../components/resource/metadata_table.ex | 22 +-- lib/ash_admin/components/resource/nav.ex | 2 +- .../resource/sensitive_attribute.ex | 2 +- lib/ash_admin/components/resource/show.ex | 183 +++++++++++++++--- lib/ash_admin/components/resource/table.ex | 8 +- .../components/top_nav/actor_select.ex | 8 +- .../components/top_nav/drawer_dropdown.ex | 4 +- lib/ash_admin/components/top_nav/dropdown.ex | 6 +- .../components/top_nav/tenant_form.ex | 2 +- lib/ash_admin/resource/resource.ex | 17 ++ 17 files changed, 376 insertions(+), 164 deletions(-) create mode 100644 dev/resources/accounts/calculations/concat.ex diff --git a/dev/resources/accounts/calculations/concat.ex b/dev/resources/accounts/calculations/concat.ex new file mode 100644 index 00000000..f9e6cfde --- /dev/null +++ b/dev/resources/accounts/calculations/concat.ex @@ -0,0 +1,30 @@ +defmodule Demo.Calculations.Concat do + use Ash.Resource.Calculation + + @impl true + def init(opts) do + if opts[:keys] && is_list(opts[:keys]) && Enum.all?(opts[:keys], &is_atom/1) do + {:ok, opts} + else + {:error, "Expected a `keys` option for which keys to concat"} + end + end + + @impl true + def load(_query, opts, _context) do + opts[:keys] + end + + @impl true + def calculate(records, opts, %{arguments: %{separator: separator}}) when is_bitstring(separator) do + Enum.map(records, fn record -> + Enum.map_join(opts[:keys], separator, fn key -> + to_string(Map.get(record, key)) + end) + end) + end + + def calculate(_records, _opts, _context) do + {:error, "Argument separator invalid"} + end +end diff --git a/dev/resources/accounts/resources/user.ex b/dev/resources/accounts/resources/user.ex index b2a52547..4bd1a9d1 100644 --- a/dev/resources/accounts/resources/user.ex +++ b/dev/resources/accounts/resources/user.ex @@ -20,6 +20,8 @@ defmodule Demo.Accounts.User do read_actions [:me, :read, :by_id, :by_name] table_columns [:id, :first_name, :last_name, :representative, :admin, :full_name, :api_key, :date_of_birth] + + show_calculations [:multi_arguments, :full_name] end multitenancy do @@ -82,7 +84,28 @@ defmodule Demo.Accounts.User do end calculations do - calculate :full_name, :string, expr(first_name <> " " <> last_name) + calculate :full_name, :string, {Demo.Calculations.Concat, keys: [:first_name, :last_name]} do + argument :separator, :string do + allow_nil? false + constraints [allow_empty?: true, trim?: false] + default " " + end + end + + calculate :is_super_admin?, :boolean, expr(admin && representative) + + calculate :multi_arguments, :string, expr("Arg1: " <> ^arg(:arg1) <> ", Arg2: " <> (if ^arg(:arg2), do: "Yes", else: "No") <> ", Arg3: " <> ^arg(:arg3)) do + argument :arg1, :string do + allow_nil? false + constraints [allow_empty?: false] + end + + argument :arg2, :boolean + + argument :arg3, :float do + allow_nil? true + end + end end attributes do diff --git a/lib/ash_admin/components/core_components.ex b/lib/ash_admin/components/core_components.ex index 1f37a145..5628854e 100644 --- a/lib/ash_admin/components/core_components.ex +++ b/lib/ash_admin/components/core_components.ex @@ -79,7 +79,7 @@ defmodule AshAdmin.CoreComponents do
- <%= render_slot(@inner_block) %> + {render_slot(@inner_block)}
@@ -122,9 +122,9 @@ defmodule AshAdmin.CoreComponents do

<.icon :if={@kind == :info} name="hero-information-circle-mini" class="h-4 w-4" /> <.icon :if={@kind == :error} name="hero-exclamation-circle-mini" class="h-4 w-4" /> - <%= @title %> + {@title}

-

<%= msg %>

+

{msg}

@@ -197,9 +197,9 @@ defmodule AshAdmin.CoreComponents do ~H""" <.form :let={f} for={@for} as={@as} {@rest}>
- <%= render_slot(@inner_block, f) %> + {render_slot(@inner_block, f)}
- <%= render_slot(action, f) %> + {render_slot(action, f)}
@@ -231,7 +231,7 @@ defmodule AshAdmin.CoreComponents do ]} {@rest} > - <%= render_slot(@inner_block) %> + {render_slot(@inner_block)} """ end @@ -312,9 +312,9 @@ defmodule AshAdmin.CoreComponents do class="rounded border-zinc-300 text-zinc-900 focus:ring-0" {@rest} /> - <%= @label %> + {@label} - <.error :for={msg <- @errors}><%= msg %> + <.error :for={msg <- @errors}>{msg} """ end @@ -322,7 +322,7 @@ defmodule AshAdmin.CoreComponents do def input(%{type: "select"} = assigns) do ~H"""
- <.label for={@id}><%= @label %> + <.label for={@id}>{@label} - <.error :for={msg <- @errors}><%= msg %> + <.error :for={msg <- @errors}>{msg}
""" end @@ -341,7 +341,7 @@ defmodule AshAdmin.CoreComponents do def input(%{type: "textarea"} = assigns) do ~H"""
- <.label for={@id}><%= @label %> + <.label for={@id}>{@label} - <.error :for={msg <- @errors}><%= msg %> + <.error :for={msg <- @errors}>{msg}
""" end @@ -362,7 +362,7 @@ defmodule AshAdmin.CoreComponents do def input(assigns) do ~H"""
- <.label for={@id}><%= @label %> + <.label for={@id}>{@label} - <.error :for={msg <- @errors}><%= msg %> + <.error :for={msg <- @errors}>{msg}
""" end @@ -390,7 +390,7 @@ defmodule AshAdmin.CoreComponents do def label(assigns) do ~H""" """ end @@ -404,7 +404,7 @@ defmodule AshAdmin.CoreComponents do ~H"""

<.icon name="hero-exclamation-circle-mini" class="mt-0.5 h-5 w-5 flex-none" /> - <%= render_slot(@inner_block) %> + {render_slot(@inner_block)}

""" end @@ -423,13 +423,13 @@ defmodule AshAdmin.CoreComponents do

- <%= render_slot(@inner_block) %> + {render_slot(@inner_block)}

- <%= render_slot(@subtitle) %> + {render_slot(@subtitle)}

-
<%= render_slot(@actions) %>
+
{render_slot(@actions)}
""" end @@ -470,8 +470,8 @@ defmodule AshAdmin.CoreComponents do - - + + - <%= render_slot(col, @row_item.(row)) %> + {render_slot(col, @row_item.(row))} @@ -499,7 +499,7 @@ defmodule AshAdmin.CoreComponents do :for={action <- @action} class="relative ml-4 font-semibold leading-6 text-zinc-900 hover:text-zinc-700" > - <%= render_slot(action, @row_item.(row)) %> + {render_slot(action, @row_item.(row))} @@ -529,8 +529,8 @@ defmodule AshAdmin.CoreComponents do
-
<%= item.title %>
-
<%= render_slot(item) %>
+
{item.title}
+
{render_slot(item)}
@@ -555,7 +555,7 @@ defmodule AshAdmin.CoreComponents do class="text-sm font-semibold leading-6 text-zinc-900 hover:text-zinc-700" > <.icon name="hero-arrow-left-solid" class="h-3 w-3" /> - <%= render_slot(@inner_block) %> + {render_slot(@inner_block)} """ diff --git a/lib/ash_admin/components/layouts.ex b/lib/ash_admin/components/layouts.ex index 16ea7dd9..f01dfa1d 100644 --- a/lib/ash_admin/components/layouts.ex +++ b/lib/ash_admin/components/layouts.ex @@ -24,7 +24,7 @@ defmodule AshAdmin.Layouts do - <%= assigns[:page_title] || "Ash Admin" %> + {assigns[:page_title] || "Ash Admin"} @@ -48,7 +48,7 @@ defmodule AshAdmin.Layouts do - <%= @inner_content %> + {@inner_content}
<%= col[:label] %><%= gettext("Actions") %>{col[:label]}{gettext("Actions")}