Skip to content

Commit

Permalink
#102 add show_resources option (#148)
Browse files Browse the repository at this point in the history
  • Loading branch information
revati authored May 15, 2024
1 parent 514ff49 commit bd4b558
Show file tree
Hide file tree
Showing 12 changed files with 158 additions and 7 deletions.
1 change: 1 addition & 0 deletions .formatter.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
7 changes: 7 additions & 0 deletions dev/resources/tickets/domain.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions documentation/dsls/DSL:-AshAdmin.Domain.md
Original file line number Diff line number Diff line change
Expand Up @@ -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. |

Expand Down
4 changes: 2 additions & 2 deletions lib/ash_admin/actor_plug/plug.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down
4 changes: 2 additions & 2 deletions lib/ash_admin/components/top_nav.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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)
Expand Down
13 changes: 12 additions & 1 deletion lib/ash_admin/domain.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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.
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion lib/ash_admin/pages/page_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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 ->
Expand Down
2 changes: 1 addition & 1 deletion lib/ash_admin/resource/resource.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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])
Expand Down
28 changes: 28 additions & 0 deletions lib/ash_admin/show_resources_transformer.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
defmodule AshAdmin.ShowResourcesTransformer do

Check warning on line 1 in lib/ash_admin/show_resources_transformer.ex

View workflow job for this annotation

GitHub Actions / ash-ci / mix credo --strict

Modules should have a @moduledoc tag.
use Spark.Dsl.Transformer

def transform(dsl) do

Check warning on line 4 in lib/ash_admin/show_resources_transformer.ex

View workflow job for this annotation

GitHub Actions / ash-ci / mix dialyzer

no_return

Function transform/1 has no local return.
module = Spark.Dsl.Transformer.get_persisted(dsl, :module)
all_resources = Ash.Domain.Info.resources(dsl)

Check warning on line 6 in lib/ash_admin/show_resources_transformer.ex

View workflow job for this annotation

GitHub Actions / ash-ci / mix dialyzer

call

The function call resources will not succeed.

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
87 changes: 87 additions & 0 deletions test/ash_admin_test.exs
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions test/support/domain.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ defmodule AshAdmin.Test.Domain do

resources do
resource(AshAdmin.Test.Post)
resource(AshAdmin.Test.Comment)
end
end
15 changes: 15 additions & 0 deletions test/support/resources/comment.ex
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit bd4b558

Please sign in to comment.