#102 add show_resources option (#148)

This commit is contained in:
Roberts Guļāns 2024-05-15 21:10:36 +03:00 committed by GitHub
parent 514ff491da
commit bd4b5581c8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 158 additions and 7 deletions

View file

@ -15,6 +15,7 @@ spark_locals_without_parens = [
resource_group_labels: 1,
show?: 1,
show_action: 1,
show_resources: 1,
show_sensitive_fields: 1,
table_columns: 1,
type: 1,

View file

@ -5,6 +5,13 @@ defmodule Demo.Tickets.Domain do
admin do
show? true
show_resources [
Demo.Tickets.Customer,
Demo.Tickets.Representative,
Demo.Tickets.Ticket,
Demo.Tickets.Comment,
Demo.Tickets.Organization
]
end
resources do

View file

@ -20,6 +20,7 @@ Configure the admin dashboard for a given domain.
|------|------|---------|------|
| [`name`](#admin-name){: #admin-name } | `String.t` | | The name of the domain in the dashboard. Will be derived if not set. |
| [`show?`](#admin-show?){: #admin-show? } | `boolean` | `false` | Whether or not this domain and its resources should be included in the admin dashboard. |
| [`show_resources`](#admin-show_resources){: #admin-show_resources } | `atom \| list(atom)` | `:*` | List of resources that should be included in the admin dashboard |
| [`default_resource_page`](#admin-default_resource_page){: #admin-default_resource_page } | `:schema \| :primary_read` | `:schema` | Set the default page for the resource to be the primary read action or the resource schema. Schema is the default for backwards compatibility, if a resource doesn't have a primary read action it will fallback to the schema view. |
| [`resource_group_labels`](#admin-resource_group_labels){: #admin-resource_group_labels } | `keyword` | `[]` | Humanized names for each resource group to appear in the admin area. These will be used as labels in the top navigation dropdown. If a key for a group does not appear in this mapping, the label will not be rendered. |

View file

@ -85,7 +85,7 @@ defmodule AshAdmin.ActorPlug.Plug do
defp actor_resources(domains) do
for domain <- domains,
resource <- Ash.Domain.Info.resources(domain),
resource <- AshAdmin.Domain.show_resources(domain),
AshAdmin.Helpers.primary_action(resource, :read) && AshAdmin.Resource.actor?(resource),
do: {domain, resource}
end
@ -120,7 +120,7 @@ defmodule AshAdmin.ActorPlug.Plug do
resource =
if domain do
domain
|> Ash.Domain.Info.resources()
|> AshAdmin.Domain.show_resources()
|> Enum.find(&(AshAdmin.Resource.name(&1) == resource))
end

View file

@ -143,7 +143,7 @@ defmodule AshAdmin.Components.TopNav do
end
defp dropdown_groups(prefix, current_resource, domain) do
for resource <- Ash.Domain.Info.resources(domain) do
for resource <- AshAdmin.Domain.show_resources(domain) do
%{
text: AshAdmin.Resource.name(resource),
to:
@ -180,7 +180,7 @@ defmodule AshAdmin.Components.TopNav do
defp show_tenant_form?(domains) do
Enum.any?(domains, fn domain ->
domain
|> Ash.Domain.Info.resources()
|> AshAdmin.Domain.show_resources()
|> Enum.any?(fn resource ->
Ash.Resource.Info.multitenancy_strategy(resource)
end)

View file

@ -13,6 +13,11 @@ defmodule AshAdmin.Domain do
doc:
"Whether or not this domain and its resources should be included in the admin dashboard."
],
show_resources: [
type: {:wrap_list, :atom},
default: :*,
doc: "List of resources that should be included in the admin dashboard"
],
default_resource_page: [
type: {:in, [:schema, :primary_read]},
default: :schema,
@ -28,7 +33,9 @@ defmodule AshAdmin.Domain do
]
}
use Spark.Dsl.Extension, sections: [@admin]
use Spark.Dsl.Extension,
sections: [@admin],
transformers: [AshAdmin.ShowResourcesTransformer]
@moduledoc """
A domain extension to alter the behavior of a domain in the admin UI.
@ -42,6 +49,10 @@ defmodule AshAdmin.Domain do
Spark.Dsl.Extension.get_opt(domain, [:admin], :show?, false, true)
end
def show_resources(domain) do
Spark.Dsl.Extension.get_opt(domain, [:admin], :show_resources, [], true)
end
def default_resource_page(domain) do
Spark.Dsl.Extension.get_opt(domain, [:admin], :default_resource_page, :schema, true)
end

View file

@ -124,7 +124,7 @@ defmodule AshAdmin.PageLive do
defp assign_resource(socket, resource) do
if socket.assigns.domain do
resources = Ash.Domain.Info.resources(socket.assigns.domain)
resources = AshAdmin.Domain.show_resources(socket.assigns.domain)
resource =
Enum.find(resources, fn domain_resources ->

View file

@ -194,7 +194,7 @@ defmodule AshAdmin.Resource do
defp find_polymorphic_tables(resource, domains) do
domains
|> Enum.flat_map(&Ash.Domain.Info.resources/1)
|> Enum.flat_map(&AshAdmin.Domain.show_resources/1)
|> Enum.flat_map(&Ash.Resource.Info.relationships/1)
|> Enum.filter(&(&1.destination == resource))
|> Enum.map(& &1.context[:data_layer][:table])

View file

@ -0,0 +1,28 @@
defmodule AshAdmin.ShowResourcesTransformer do
use Spark.Dsl.Transformer
def transform(dsl) do
module = Spark.Dsl.Transformer.get_persisted(dsl, :module)
all_resources = Ash.Domain.Info.resources(dsl)
resources =
case AshAdmin.Domain.show_resources(dsl) do
[:*] ->
all_resources
resources ->
case Enum.find(resources, &(&1 not in all_resources)) do
nil ->
resources
bad_resource ->
raise Spark.Error.DslError,
module: module,
path: [:admin, :show_resources],
message: "#{inspect(bad_resource)} is not a valid resource in #{inspect(module)}"
end
end
{:ok, Spark.Dsl.Transformer.set_option(dsl, [:admin], :show_resources, resources)}
end
end

View file

@ -1,4 +1,91 @@
defmodule AshAdmin.Test.AshAdminTest do
@moduledoc false
use ExUnit.Case, async: true
test "all resources are shown by default", _ do
defmodule Domain do
@moduledoc false
use Ash.Domain,
extensions: [AshAdmin.Domain]
admin do
show? true
end
resources do
resource AshAdmin.Test.Post
resource AshAdmin.Test.Comment
end
end
assert AshAdmin.Domain.show_resources(Domain) === [
AshAdmin.Test.Post,
AshAdmin.Test.Comment
]
end
test "all resources are shown when :* option is selected", _ do
defmodule Domain do
@moduledoc false
use Ash.Domain,
extensions: [AshAdmin.Domain]
admin do
show? true
show_resources :*
end
resources do
resource AshAdmin.Test.Post
resource AshAdmin.Test.Comment
end
end
assert AshAdmin.Domain.show_resources(Domain) === [
AshAdmin.Test.Post,
AshAdmin.Test.Comment
]
end
test "selected resources are shown", _ do
defmodule Domain do
@moduledoc false
use Ash.Domain,
extensions: [AshAdmin.Domain]
admin do
show? true
show_resources AshAdmin.Test.Post
end
resources do
resource AshAdmin.Test.Post
resource AshAdmin.Test.Comment
end
end
assert AshAdmin.Domain.show_resources(Domain) === [
AshAdmin.Test.Post
]
end
test "if shown resrouces option not eixsting resource providede error", _ do
assert_raise(Spark.Error.DslError, "[AshAdmin.Test.AshAdminTest.Domain]\n admin -> show_resources:\n SomeRandom is not a valid resource in AshAdmin.Test.AshAdminTest.Domain", fn ->
defmodule Domain do
@moduledoc false
use Ash.Domain,
extensions: [AshAdmin.Domain]
admin do
show? true
show_resources [AshAdmin.Test.Post, SomeRandom]
end
resources do
resource AshAdmin.Test.Post
resource AshAdmin.Test.Comment
end
end
end)
end
end

View file

@ -9,5 +9,6 @@ defmodule AshAdmin.Test.Domain do
resources do
resource(AshAdmin.Test.Post)
resource(AshAdmin.Test.Comment)
end
end

View file

@ -0,0 +1,15 @@
defmodule AshAdmin.Test.Comment do
@moduledoc false
use Ash.Resource,
domain: AshAdmin.Test.Domain,
data_layer: Ash.DataLayer.Ets
attributes do
uuid_primary_key(:id)
attribute :body, :string do
allow_nil?(false)
public?(true)
end
end
end