mirror of
https://github.com/ash-project/ash_admin.git
synced 2024-09-19 12:53:28 +12:00
improvement: upgrade to 3.0
This commit is contained in:
parent
7e303883ee
commit
657d36d3e2
42 changed files with 381 additions and 362 deletions
7
.github/ISSUE_TEMPLATE/proposal.md
vendored
7
.github/ISSUE_TEMPLATE/proposal.md
vendored
|
@ -1,10 +1,9 @@
|
|||
---
|
||||
name: Proposal
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
title: ""
|
||||
labels: enhancement, needs review
|
||||
assignees: ''
|
||||
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
|
@ -29,7 +28,7 @@ For example
|
|||
Or
|
||||
|
||||
```elixir
|
||||
Api.read(:resource, bar: 10) # <- Adding `bar` here would cause <x>
|
||||
Ash.read(:resource, bar: 10) # <- Adding `bar` here would cause <x>
|
||||
```
|
||||
|
||||
**Additional context**
|
||||
|
|
17
README.md
17
README.md
|
@ -21,29 +21,30 @@ First, ensure you've added ash_admin to your `mix.exs` file.
|
|||
|
||||
## Setup
|
||||
|
||||
Ensure your apis are configured in `config.exs`
|
||||
Ensure your domains are configured in `config.exs`
|
||||
|
||||
```elixir
|
||||
config :my_app, ash_apis: [MyApp.Foo, MyApp.Bar]
|
||||
config :my_app, ash_domains: [MyApp.Foo, MyApp.Bar]
|
||||
```
|
||||
|
||||
Add the admin extension to each api you want to show in AshAdmin dashboard, and configure it to show. See [`AshAdmin.Api`](https://hexdocs.pm/ash_admin/AshAdmin.Api.html) for more configuration options.
|
||||
Add the admin extension to each domain you want to show in AshAdmin dashboard, and configure it to show. See [`AshAdmin.Domain`](https://hexdocs.pm/ash_admin/AshAdmin.Domain.html) for more configuration options.
|
||||
|
||||
```elixir
|
||||
# In your Api(s)
|
||||
use Ash.Api,
|
||||
extensions: [AshAdmin.Api]
|
||||
# In your Domain(s)
|
||||
use Ash.Domain,
|
||||
extensions: [AshAdmin.Domain]
|
||||
|
||||
admin do
|
||||
show? true
|
||||
end
|
||||
```
|
||||
|
||||
Resources in each Api will be automagically included in AshAdmin. See [`AshAdmin.Resource`](https://hexdocs.pm/ash_admin/AshAdmin.Resource.html) for more resource configuration options. Specifically, if you app has an actor you will want to configure that. Ash Admin allows you to change actors and therefore doesn't rely on `Ash.set_actor`
|
||||
Resources in each Domain will be included in AshAdmin. See [`AshAdmin.Resource`](https://hexdocs.pm/ash_admin/AshAdmin.Resource.html) for more resource configuration options. Specifically, if you app has an actor you will want to configure that. Ash Admin allows you to change actors and therefore doesn't rely on `Ash.set_actor`
|
||||
|
||||
```elixir
|
||||
# In your resource that acts as an actor (e.g. User)
|
||||
use Ash.Resource,
|
||||
domain: YourDomain,
|
||||
extensions: [AshAdmin.Resource]
|
||||
|
||||
admin do
|
||||
|
@ -103,7 +104,7 @@ This will allow AshAdmin-generated inline CSS and JS blocks to execute normally.
|
|||
|
||||
## Configuration
|
||||
|
||||
See the documentation in [`AshAdmin.Resource`](https://hexdocs.pm/ash_admin/AshAdmin.Resource.html) and [`AshAdmin.Api`](https://hexdocs.pm/ash_admin/AshAdmin.Api.html) for information on the available configuration.
|
||||
See the documentation in [`AshAdmin.Resource`](https://hexdocs.pm/ash_admin/AshAdmin.Resource.html) and [`AshAdmin.Domain`](https://hexdocs.pm/ash_admin/AshAdmin.Domain.html) for information on the available configuration.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ Hooks.JsonEditor = {
|
|||
},
|
||||
modes: ["text", "tree"],
|
||||
},
|
||||
JSON.parse(document.getElementById(inputId).value)
|
||||
JSON.parse(document.getElementById(inputId).value),
|
||||
);
|
||||
|
||||
editors[this.el.id] = this.editor;
|
||||
|
@ -71,7 +71,7 @@ Hooks.JsonView = {
|
|||
{
|
||||
mode: "preview",
|
||||
},
|
||||
json
|
||||
json,
|
||||
);
|
||||
},
|
||||
mounted() {
|
||||
|
@ -81,7 +81,7 @@ Hooks.JsonView = {
|
|||
{
|
||||
mode: "preview",
|
||||
},
|
||||
json
|
||||
json,
|
||||
);
|
||||
},
|
||||
};
|
||||
|
@ -111,13 +111,13 @@ Hooks.Actor = {
|
|||
document.cookie =
|
||||
"actor_primary_key" + "=" + payload.primary_key + ";path=/";
|
||||
document.cookie = "actor_action" + "=" + payload.action + ";path=/";
|
||||
document.cookie = "actor_api" + "=" + payload.api + ";path=/";
|
||||
document.cookie = "actor_domain" + "=" + payload.domain + ";path=/";
|
||||
});
|
||||
this.handleEvent("clear_actor", () => {
|
||||
document.cookie = "actor_resource" + "=" + ";path=/";
|
||||
document.cookie = "actor_primary_key" + "=" + ";path=/";
|
||||
document.cookie = "actor_action" + ";path=/";
|
||||
document.cookie = "actor_api" + "=" + ";path=/";
|
||||
document.cookie = "actor_domain" + "=" + ";path=/";
|
||||
document.cookie = "actor_authorizing=false;path=/";
|
||||
document.cookie = "actor_paused=true;path=/";
|
||||
});
|
||||
|
@ -160,9 +160,8 @@ Hooks.MaintainAttrs = {
|
|||
function getCookie(name) {
|
||||
var re = new RegExp(name + "=([^;]+)");
|
||||
var value = re.exec(document.cookie);
|
||||
return (value != null) ? unescape(value[1]) : null;
|
||||
};
|
||||
|
||||
return value != null ? unescape(value[1]) : null;
|
||||
}
|
||||
|
||||
let params = () => {
|
||||
return {
|
||||
|
@ -171,11 +170,11 @@ let params = () => {
|
|||
actor_resource: getCookie("actor_resource"),
|
||||
actor_primary_key: getCookie("actor_primary_key"),
|
||||
actor_action: getCookie("actor_action"),
|
||||
actor_api: getCookie("actor_api"),
|
||||
actor_domain: getCookie("actor_domain"),
|
||||
actor_authorizing: getCookie("actor_authorizing"),
|
||||
actor_paused: getCookie("actor_paused")
|
||||
}
|
||||
}
|
||||
actor_paused: getCookie("actor_paused"),
|
||||
};
|
||||
};
|
||||
|
||||
let liveSocket = new LiveSocket(socketPath, Socket, {
|
||||
params: params,
|
||||
|
|
|
@ -44,9 +44,9 @@ config :phoenix, :serve_endpoints, true
|
|||
|
||||
if config_env() == :dev do
|
||||
config :ash_admin,
|
||||
ash_apis: [
|
||||
Demo.Accounts.Api,
|
||||
Demo.Tickets.Api
|
||||
ash_domains: [
|
||||
Demo.Accounts.Domain,
|
||||
Demo.Tickets.Domain
|
||||
]
|
||||
|
||||
config :git_ops,
|
||||
|
@ -73,7 +73,7 @@ if config_env() == :test do
|
|||
config :ash, :disable_async?, true
|
||||
|
||||
config :ash_admin,
|
||||
ash_apis: [
|
||||
AshAdmin.Test.Api
|
||||
ash_domains: [
|
||||
AshAdmin.Test.Domain
|
||||
]
|
||||
end
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
defmodule Demo.Accounts.Api do
|
||||
@moduledoc false
|
||||
use Ash.Api,
|
||||
extensions: [AshAdmin.Api]
|
||||
|
||||
admin do
|
||||
show? true
|
||||
end
|
||||
|
||||
resources do
|
||||
registry Demo.Accounts.Registry
|
||||
end
|
||||
end
|
13
dev/resources/accounts/domain.ex
Normal file
13
dev/resources/accounts/domain.ex
Normal file
|
@ -0,0 +1,13 @@
|
|||
defmodule Demo.Accounts.Domain do
|
||||
@moduledoc false
|
||||
use Ash.Domain,
|
||||
extensions: [AshAdmin.Domain]
|
||||
|
||||
admin do
|
||||
show? true
|
||||
end
|
||||
|
||||
resources do
|
||||
resource Demo.Accounts.User
|
||||
end
|
||||
end
|
|
@ -1,7 +0,0 @@
|
|||
defmodule Demo.Accounts.Registry do
|
||||
use Ash.Registry
|
||||
|
||||
entries do
|
||||
entry Demo.Accounts.User
|
||||
end
|
||||
end
|
|
@ -1,16 +1,8 @@
|
|||
defmodule Demo.Accounts.NestedEmbed do
|
||||
use Ash.Resource,
|
||||
data_layer: :embedded,
|
||||
extensions: [AshAdmin.Resource]
|
||||
|
||||
admin do
|
||||
form do
|
||||
field :bio, type: :long_text
|
||||
field :history, type: :long_text
|
||||
end
|
||||
end
|
||||
data_layer: :embedded
|
||||
|
||||
attributes do
|
||||
attribute :tags, {:array, :string}, default: []
|
||||
attribute :tags, {:array, :string}, default: [], public?: true
|
||||
end
|
||||
end
|
||||
|
|
|
@ -11,10 +11,10 @@ defmodule Demo.Accounts.Profile do
|
|||
end
|
||||
|
||||
attributes do
|
||||
attribute :bio, :string, allow_nil?: false
|
||||
attribute :history, :string
|
||||
attribute :tags, {:array, :string}, default: []
|
||||
attribute :metadata, :map
|
||||
attribute :nested_embed, Demo.Accounts.NestedEmbed
|
||||
attribute :bio, :string, allow_nil?: false, public?: true
|
||||
attribute :history, :string, public?: true
|
||||
attribute :tags, {:array, :string}, default: [], public?: true
|
||||
attribute :metadata, :map, public?: true
|
||||
attribute :nested_embed, Demo.Accounts.NestedEmbed, public?: true
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
defmodule Demo.Accounts.User do
|
||||
use Ash.Resource,
|
||||
domain: Demo.Accounts.Domain,
|
||||
data_layer: AshPostgres.DataLayer,
|
||||
authorizers: [
|
||||
Ash.Policy.Authorizer
|
||||
|
@ -38,6 +39,7 @@ defmodule Demo.Accounts.User do
|
|||
end
|
||||
|
||||
actions do
|
||||
default_accept :*
|
||||
read :me, filter: [id: actor(:id)]
|
||||
read :read, primary?: true
|
||||
read :by_id do
|
||||
|
@ -80,16 +82,21 @@ defmodule Demo.Accounts.User do
|
|||
|
||||
attribute :first_name, :string do
|
||||
constraints min_length: 1
|
||||
public? true
|
||||
end
|
||||
|
||||
attribute :last_name, :string do
|
||||
constraints min_length: 1
|
||||
public? true
|
||||
end
|
||||
|
||||
attribute :metadata, :map
|
||||
attribute :metadata, :map do
|
||||
public? true
|
||||
end
|
||||
|
||||
attribute :representative, :boolean do
|
||||
allow_nil? false
|
||||
public? true
|
||||
default false
|
||||
description """
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
|
||||
|
@ -102,30 +109,39 @@ defmodule Demo.Accounts.User do
|
|||
end
|
||||
|
||||
attribute :admin, :boolean do
|
||||
public? true
|
||||
allow_nil? false
|
||||
default false
|
||||
end
|
||||
|
||||
attribute :api_key, :string do
|
||||
private? true
|
||||
sensitive? true
|
||||
end
|
||||
|
||||
attribute :date_of_birth, :date do
|
||||
public? true
|
||||
sensitive? true
|
||||
end
|
||||
|
||||
attribute :profile, Demo.Accounts.Profile
|
||||
attribute :alternate_profiles, {:array, Demo.Accounts.Profile}
|
||||
attribute :profile, Demo.Accounts.Profile do
|
||||
public? true
|
||||
end
|
||||
attribute :alternate_profiles, {:array, Demo.Accounts.Profile} do
|
||||
public? true
|
||||
end
|
||||
attribute :type, :atom do
|
||||
public? true
|
||||
constraints one_of: [:type1, :type2]
|
||||
default :type1
|
||||
end
|
||||
|
||||
attribute :types, {:array, :atom} do
|
||||
public? true
|
||||
constraints items: [one_of: [:type1, :type2]]
|
||||
end
|
||||
attribute :tags, {:array, :string}
|
||||
attribute :tags, {:array, :string} do
|
||||
public? true
|
||||
end
|
||||
|
||||
timestamps()
|
||||
end
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
defmodule Demo.Tickets.Api do
|
||||
@moduledoc false
|
||||
use Ash.Api,
|
||||
extensions: [AshAdmin.Api]
|
||||
|
||||
admin do
|
||||
show? true
|
||||
end
|
||||
|
||||
resources do
|
||||
registry Demo.Tickets.Registry
|
||||
end
|
||||
end
|
|
@ -1,5 +1,6 @@
|
|||
defmodule Demo.Tickets.Comment do
|
||||
use Ash.Resource,
|
||||
domain: Demo.Tickets.Domain,
|
||||
data_layer: AshPostgres.DataLayer,
|
||||
extensions: [AshAdmin.Resource]
|
||||
|
||||
|
@ -10,6 +11,7 @@ defmodule Demo.Tickets.Comment do
|
|||
end
|
||||
|
||||
actions do
|
||||
default_accept :*
|
||||
defaults [:read, :update, :destroy]
|
||||
create :create do
|
||||
primary? true
|
||||
|
@ -29,12 +31,12 @@ defmodule Demo.Tickets.Comment do
|
|||
attributes do
|
||||
uuid_primary_key :id
|
||||
|
||||
attribute :comment, :string
|
||||
attribute :resource_id, :uuid, allow_nil?: false
|
||||
attribute :comment, :string, public?: true
|
||||
attribute :resource_id, :uuid, allow_nil?: false, public?: true
|
||||
end
|
||||
|
||||
relationships do
|
||||
belongs_to :commenting_customer, Demo.Tickets.Customer
|
||||
belongs_to :commenting_representative, Demo.Tickets.Representative
|
||||
belongs_to :commenting_customer, Demo.Tickets.Customer, public?: true
|
||||
belongs_to :commenting_representative, Demo.Tickets.Representative, public?: true
|
||||
end
|
||||
end
|
||||
|
|
18
dev/resources/tickets/domain.ex
Normal file
18
dev/resources/tickets/domain.ex
Normal file
|
@ -0,0 +1,18 @@
|
|||
defmodule Demo.Tickets.Domain do
|
||||
@moduledoc false
|
||||
use Ash.Domain,
|
||||
extensions: [AshAdmin.Domain]
|
||||
|
||||
admin do
|
||||
show? true
|
||||
end
|
||||
|
||||
resources do
|
||||
resource(Demo.Tickets.Customer)
|
||||
resource(Demo.Tickets.Representative)
|
||||
resource(Demo.Tickets.Ticket)
|
||||
resource(Demo.Tickets.Comment)
|
||||
resource(Demo.Tickets.TicketLink)
|
||||
resource(Demo.Tickets.Organization)
|
||||
end
|
||||
end
|
|
@ -1,13 +0,0 @@
|
|||
defmodule Demo.Tickets.Registry do
|
||||
use Ash.Registry
|
||||
alias Demo.Tickets.{Comment, Customer, Representative, Ticket, TicketLink, Organization}
|
||||
|
||||
entries do
|
||||
entry(Customer)
|
||||
entry(Representative)
|
||||
entry(Ticket)
|
||||
entry(Comment)
|
||||
entry(TicketLink)
|
||||
entry(Organization)
|
||||
end
|
||||
end
|
|
@ -1,5 +1,6 @@
|
|||
defmodule Demo.Tickets.Customer do
|
||||
use Ash.Resource,
|
||||
domain: Demo.Tickets.Domain,
|
||||
data_layer: AshPostgres.DataLayer,
|
||||
authorizers: [
|
||||
Ash.Policy.Authorizer
|
||||
|
@ -33,15 +34,16 @@ defmodule Demo.Tickets.Customer do
|
|||
end
|
||||
|
||||
actions do
|
||||
default_accept :*
|
||||
defaults [:read]
|
||||
end
|
||||
|
||||
attributes do
|
||||
uuid_primary_key :id
|
||||
|
||||
attribute :first_name, :string
|
||||
attribute :last_name, :string
|
||||
attribute :representative, :boolean
|
||||
attribute :first_name, :string, public?: true
|
||||
attribute :last_name, :string, public?: true
|
||||
attribute :representative, :boolean, public?: true
|
||||
end
|
||||
|
||||
relationships do
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
defmodule Demo.Tickets.Organization do
|
||||
use Ash.Resource,
|
||||
domain: Demo.Tickets.Domain,
|
||||
data_layer: AshPostgres.DataLayer
|
||||
|
||||
postgres do
|
||||
|
@ -8,16 +9,17 @@ defmodule Demo.Tickets.Organization do
|
|||
end
|
||||
|
||||
actions do
|
||||
default_accept :*
|
||||
defaults [:create, :read, :update, :destroy]
|
||||
end
|
||||
|
||||
attributes do
|
||||
uuid_primary_key :id
|
||||
|
||||
attribute :name, :string
|
||||
attribute :name, :string, public?: true
|
||||
end
|
||||
|
||||
relationships do
|
||||
has_many :tickets, Demo.Tickets.Ticket
|
||||
has_many :tickets, Demo.Tickets.Ticket, public?: true
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
defmodule Demo.Tickets.Representative do
|
||||
use Ash.Resource,
|
||||
domain: Demo.Tickets.Domain,
|
||||
data_layer: AshPostgres.DataLayer,
|
||||
authorizers: [
|
||||
Ash.Policy.Authorizer
|
||||
|
@ -38,6 +39,7 @@ defmodule Demo.Tickets.Representative do
|
|||
end
|
||||
|
||||
actions do
|
||||
default_accept :*
|
||||
defaults []
|
||||
read :read do
|
||||
primary? true
|
||||
|
@ -56,9 +58,9 @@ defmodule Demo.Tickets.Representative do
|
|||
attributes do
|
||||
uuid_primary_key :id
|
||||
|
||||
attribute :first_name, :string
|
||||
attribute :last_name, :string
|
||||
attribute :representative, :boolean
|
||||
attribute :first_name, :string, public?: true
|
||||
attribute :last_name, :string, public?: true
|
||||
attribute :representative, :boolean, public?: true
|
||||
end
|
||||
|
||||
aggregates do
|
||||
|
@ -71,10 +73,12 @@ defmodule Demo.Tickets.Representative do
|
|||
|
||||
relationships do
|
||||
has_many :assigned_tickets, Demo.Tickets.Ticket do
|
||||
public? true
|
||||
destination_attribute :representative_id
|
||||
end
|
||||
|
||||
has_many :comments, Demo.Tickets.Comment do
|
||||
public? true
|
||||
relationship_context %{data_layer: %{table: "representative_comments"}}
|
||||
destination_attribute :resource_id
|
||||
end
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
defmodule Demo.Tickets.Ticket do
|
||||
use Ash.Resource,
|
||||
domain: Demo.Tickets.Domain,
|
||||
data_layer: AshPostgres.DataLayer,
|
||||
authorizers: [
|
||||
Ash.Policy.Authorizer
|
||||
|
@ -38,6 +39,7 @@ defmodule Demo.Tickets.Ticket do
|
|||
end
|
||||
|
||||
actions do
|
||||
default_accept :*
|
||||
read :reported do
|
||||
filter reporter: actor(:id)
|
||||
|
||||
|
@ -82,6 +84,7 @@ defmodule Demo.Tickets.Ticket do
|
|||
|
||||
update :assign do
|
||||
accept []
|
||||
require_atomic? false
|
||||
argument :representative, :map
|
||||
argument :reassignment_comment, :map, allow_nil?: false
|
||||
|
||||
|
@ -91,6 +94,7 @@ defmodule Demo.Tickets.Ticket do
|
|||
|
||||
update :link do
|
||||
accept []
|
||||
require_atomic? false
|
||||
argument :tickets, {:array, :map}, allow_nil?: false
|
||||
argument :link_comment, :map
|
||||
|
||||
|
@ -102,6 +106,7 @@ defmodule Demo.Tickets.Ticket do
|
|||
update :nested_example do
|
||||
accept [:subject]
|
||||
argument :tickets, {:array, :map}
|
||||
require_atomic? false
|
||||
|
||||
change manage_relationship(
|
||||
:tickets,
|
||||
|
@ -127,14 +132,20 @@ defmodule Demo.Tickets.Ticket do
|
|||
|
||||
attribute :subject, :string do
|
||||
allow_nil? false
|
||||
public? true
|
||||
constraints min_length: 5
|
||||
end
|
||||
|
||||
attribute :description, :string
|
||||
attribute :description, :string do
|
||||
public? true
|
||||
end
|
||||
|
||||
attribute :response, :string
|
||||
attribute :response, :string do
|
||||
public? true
|
||||
end
|
||||
|
||||
attribute :status, :atom do
|
||||
public? true
|
||||
allow_nil? false
|
||||
default "new"
|
||||
constraints one_of: [:new, :investigating, :closed]
|
||||
|
@ -148,25 +159,29 @@ defmodule Demo.Tickets.Ticket do
|
|||
end
|
||||
|
||||
relationships do
|
||||
belongs_to :reporter, Demo.Tickets.Customer
|
||||
belongs_to :reporter, Demo.Tickets.Customer, public?: true
|
||||
|
||||
belongs_to :representative, Demo.Tickets.Representative
|
||||
belongs_to :representative, Demo.Tickets.Representative, public?: true
|
||||
belongs_to :organization, Demo.Tickets.Organization do
|
||||
public? true
|
||||
allow_nil? false
|
||||
end
|
||||
|
||||
has_many :comments, Demo.Tickets.Comment do
|
||||
public? true
|
||||
relationship_context %{data_layer: %{table: "ticket_comments"}}
|
||||
destination_attribute :resource_id
|
||||
end
|
||||
|
||||
many_to_many :source_links, Demo.Tickets.Ticket do
|
||||
public? true
|
||||
through Demo.Tickets.TicketLink
|
||||
source_attribute_on_join_resource :source_id
|
||||
destination_attribute_on_join_resource :destination_id
|
||||
end
|
||||
|
||||
many_to_many :destination_links, Demo.Tickets.Ticket do
|
||||
public? true
|
||||
through Demo.Tickets.TicketLink
|
||||
source_attribute_on_join_resource :destination_id
|
||||
destination_attribute_on_join_resource :source_id
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
defmodule Demo.Tickets.TicketLink do
|
||||
use Ash.Resource,
|
||||
domain: Demo.Tickets.Domain,
|
||||
data_layer: AshPostgres.DataLayer
|
||||
|
||||
postgres do
|
||||
|
@ -10,20 +11,23 @@ defmodule Demo.Tickets.TicketLink do
|
|||
attributes do
|
||||
attribute :type, :atom, constraints: [
|
||||
one_of: [:causes, :caused_by, :fixes, :fixed_by]
|
||||
], allow_nil?: false
|
||||
], allow_nil?: false, public?: true
|
||||
end
|
||||
|
||||
actions do
|
||||
default_accept :*
|
||||
defaults [:create, :read, :update, :destroy]
|
||||
end
|
||||
|
||||
relationships do
|
||||
belongs_to :source, Demo.Tickets.Ticket do
|
||||
public? true
|
||||
primary_key? true
|
||||
allow_nil? false
|
||||
end
|
||||
|
||||
belongs_to :destination, Demo.Tickets.Ticket do
|
||||
public? true
|
||||
primary_key? true
|
||||
allow_nil? false
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<!--
|
||||
This file was generated by Spark. Do not edit it by hand.
|
||||
-->
|
||||
# DSL: AshAdmin.Api
|
||||
# DSL: AshAdmin.Domain
|
||||
|
||||
An API extension to alter the behavior of an API in the admin UI.
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ defmodule AshAdmin.ActorPlug.Plug do
|
|||
@impl true
|
||||
def actor_assigns(socket, session) do
|
||||
otp_app = socket.endpoint.config(:otp_app)
|
||||
apis = apis(otp_app)
|
||||
domains = domains(otp_app)
|
||||
|
||||
session =
|
||||
Phoenix.LiveView.get_connect_params(socket) || session
|
||||
|
@ -21,8 +21,8 @@ defmodule AshAdmin.ActorPlug.Plug do
|
|||
|
||||
[
|
||||
actor: actor_from_session(socket.endpoint, session),
|
||||
actor_api: actor_api_from_session(socket.endpoint, session),
|
||||
actor_resources: actor_resources(apis),
|
||||
actor_domain: actor_domain_from_session(socket.endpoint, session),
|
||||
actor_resources: actor_resources(domains),
|
||||
authorizing: session_bool(session["actor_authorizing"]),
|
||||
tenant: session["tenant"],
|
||||
actor_paused: actor_paused
|
||||
|
@ -50,7 +50,7 @@ defmodule AshAdmin.ActorPlug.Plug do
|
|||
case session do
|
||||
%{
|
||||
"actor_resource" => resource,
|
||||
"actor_api" => api,
|
||||
"actor_domain" => domain,
|
||||
"actor_action" => action,
|
||||
"actor_primary_key" => primary_key
|
||||
} ->
|
||||
|
@ -70,7 +70,7 @@ defmodule AshAdmin.ActorPlug.Plug do
|
|||
|
||||
conn
|
||||
|> Plug.Conn.put_session(:actor_resource, resource)
|
||||
|> Plug.Conn.put_session(:actor_api, api)
|
||||
|> Plug.Conn.put_session(:actor_domain, domain)
|
||||
|> Plug.Conn.put_session(:actor_action, action)
|
||||
|> Plug.Conn.put_session(:actor_primary_key, primary_key)
|
||||
|> Plug.Conn.put_session(:actor_authorizing, authorizing)
|
||||
|
@ -105,60 +105,60 @@ defmodule AshAdmin.ActorPlug.Plug do
|
|||
end
|
||||
end
|
||||
|
||||
defp actor_resources(apis) do
|
||||
apis
|
||||
|> Enum.flat_map(fn api ->
|
||||
api
|
||||
|> Ash.Api.Info.resources()
|
||||
defp actor_resources(domains) do
|
||||
domains
|
||||
|> Enum.flat_map(fn domain ->
|
||||
domain
|
||||
|> Ash.Domain.Info.resources()
|
||||
|> Enum.filter(fn resource ->
|
||||
AshAdmin.Helpers.primary_action(resource, :read) && AshAdmin.Resource.actor?(resource)
|
||||
end)
|
||||
|> Enum.map(fn resource -> {api, resource} end)
|
||||
|> Enum.map(fn resource -> {domain, resource} end)
|
||||
end)
|
||||
end
|
||||
|
||||
defp apis(otp_app) do
|
||||
defp domains(otp_app) do
|
||||
otp_app
|
||||
|> Application.get_env(:ash_apis)
|
||||
|> Enum.filter(&AshAdmin.Api.show?/1)
|
||||
|> Application.get_env(:ash_domains)
|
||||
|> Enum.filter(&AshAdmin.Domain.show?/1)
|
||||
end
|
||||
|
||||
defp actor_api_from_session(endpoint, %{"actor_api" => api}) do
|
||||
defp actor_domain_from_session(endpoint, %{"actor_domain" => domain}) do
|
||||
otp_app = endpoint.config(:otp_app)
|
||||
apis = Application.get_env(otp_app, :ash_apis)
|
||||
domains = Application.get_env(otp_app, :ash_domains)
|
||||
|
||||
Enum.find(apis, fn allowed_api ->
|
||||
AshAdmin.Api.show?(allowed_api) && AshAdmin.Api.name(allowed_api) == api
|
||||
Enum.find(domains, fn allowed_domain ->
|
||||
AshAdmin.Domain.show?(allowed_domain) && AshAdmin.Domain.name(allowed_domain) == domain
|
||||
end)
|
||||
end
|
||||
|
||||
defp actor_api_from_session(_, _), do: nil
|
||||
defp actor_domain_from_session(_, _), do: nil
|
||||
|
||||
defp actor_from_session(endpoint, %{
|
||||
"actor_resource" => resource,
|
||||
"actor_api" => api,
|
||||
"actor_domain" => domain,
|
||||
"actor_primary_key" => primary_key,
|
||||
"actor_action" => action
|
||||
})
|
||||
when not is_nil(resource) and not is_nil(api) do
|
||||
when not is_nil(resource) and not is_nil(domain) do
|
||||
otp_app = endpoint.config(:otp_app)
|
||||
apis = Application.get_env(otp_app, :ash_apis)
|
||||
domains = Application.get_env(otp_app, :ash_domains)
|
||||
|
||||
api =
|
||||
Enum.find(apis, fn allowed_api ->
|
||||
AshAdmin.Api.show?(allowed_api) && AshAdmin.Api.name(allowed_api) == api
|
||||
domain =
|
||||
Enum.find(domains, fn allowed_domain ->
|
||||
AshAdmin.Domain.show?(allowed_domain) && AshAdmin.Domain.name(allowed_domain) == domain
|
||||
end)
|
||||
|
||||
resource =
|
||||
if api do
|
||||
api
|
||||
|> Ash.Api.Info.resources()
|
||||
|> Enum.find(fn api_resource ->
|
||||
AshAdmin.Resource.name(api_resource) == resource
|
||||
if domain do
|
||||
domain
|
||||
|> Ash.Domain.Info.resources()
|
||||
|> Enum.find(fn domain_resource ->
|
||||
AshAdmin.Resource.name(domain_resource) == resource
|
||||
end)
|
||||
end
|
||||
|
||||
if api && resource do
|
||||
if domain && resource do
|
||||
action =
|
||||
if action do
|
||||
Ash.Resource.Info.action(resource, String.to_existing_atom(action), :read)
|
||||
|
@ -171,7 +171,7 @@ defmodule AshAdmin.ActorPlug.Plug do
|
|||
{:ok, filter} ->
|
||||
resource
|
||||
|> Ash.Query.filter(^filter)
|
||||
|> api.read_one!(action: action, authorize?: false)
|
||||
|> Ash.read_one!(action: action, authorize?: false, domain: domain)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,7 +8,7 @@ defmodule AshAdmin.Components.Resource.DataTable do
|
|||
alias AshAdmin.Components.Resource.Table
|
||||
|
||||
attr :resource, :atom
|
||||
attr :api, :atom
|
||||
attr :domain, :atom
|
||||
attr :action, :any
|
||||
attr :authorizing, :boolean
|
||||
attr :actor, :any
|
||||
|
@ -100,7 +100,7 @@ defmodule AshAdmin.Components.Resource.DataTable do
|
|||
table={@table}
|
||||
data={data(@data)}
|
||||
resource={@resource}
|
||||
api={@api}
|
||||
domain={@domain}
|
||||
attributes={AshAdmin.Resource.table_columns(@resource)}
|
||||
format_fields={AshAdmin.Resource.format_fields(@resource)}
|
||||
show_sensitive_fields={AshAdmin.Resource.show_sensitive_fields(@resource)}
|
||||
|
@ -212,7 +212,7 @@ defmodule AshAdmin.Components.Resource.DataTable do
|
|||
socket.assigns.query.source
|
||||
|> set_table(socket.assigns[:table])
|
||||
|> load_fields()
|
||||
|> assigns[:api].read(page: page_params)
|
||||
|> Ash.read(page: page_params, domain: assigns[:domain])
|
||||
end
|
||||
end,
|
||||
load_until_connected?: true
|
||||
|
@ -230,7 +230,7 @@ defmodule AshAdmin.Components.Resource.DataTable do
|
|||
|> set_table(socket.assigns[:table])
|
||||
|> Ash.Query.limit(1000)
|
||||
|> load_fields()
|
||||
|> assigns[:api].read()
|
||||
|> Ash.read(domain: assigns[:domain])
|
||||
end
|
||||
end,
|
||||
load_until_connected?: true
|
||||
|
|
|
@ -9,7 +9,7 @@ defmodule AshAdmin.Components.Resource.Form do
|
|||
require Logger
|
||||
|
||||
attr :resource, :any, required: true
|
||||
attr :api, :any, required: true
|
||||
attr :domain, :any, required: true
|
||||
attr :record, :any, default: nil
|
||||
attr :type, :atom, default: nil
|
||||
attr :actor, :any, default: nil
|
||||
|
@ -1043,10 +1043,10 @@ defmodule AshAdmin.Components.Resource.Form do
|
|||
type
|
||||
|> Ash.Resource.Info.primary_key()
|
||||
|> Enum.flat_map(fn attr ->
|
||||
if Ash.Resource.Info.attribute(type, attr).private? do
|
||||
[]
|
||||
else
|
||||
if Ash.Resource.Info.attribute(type, attr).public? do
|
||||
[attr]
|
||||
else
|
||||
[]
|
||||
end
|
||||
end)
|
||||
|> Enum.join("-")
|
||||
|
@ -1109,7 +1109,7 @@ defmodule AshAdmin.Components.Resource.Form do
|
|||
socket
|
||||
|> redirect(
|
||||
to:
|
||||
"#{socket.assigns.prefix || "/"}?api=#{AshAdmin.Api.name(socket.assigns.api)}&resource=#{AshAdmin.Resource.name(socket.assigns.resource)}&tab=show&table=#{socket.assigns.table}&primary_key=#{encode_primary_key(record)}"
|
||||
"#{socket.assigns.prefix || "/"}?domain=#{AshAdmin.Domain.name(socket.assigns.domain)}&resource=#{AshAdmin.Resource.name(socket.assigns.resource)}&tab=show&table=#{socket.assigns.table}&primary_key=#{encode_primary_key(record)}"
|
||||
)}
|
||||
else
|
||||
case AshAdmin.Helpers.primary_action(socket.assigns.resource, :update) do
|
||||
|
@ -1117,7 +1117,7 @@ defmodule AshAdmin.Components.Resource.Form do
|
|||
{:noreply,
|
||||
redirect(socket,
|
||||
to:
|
||||
"#{socket.assigns.prefix || "/"}?api=#{AshAdmin.Api.name(socket.assigns.api)}&resource=#{AshAdmin.Resource.name(socket.assigns.resource)}"
|
||||
"#{socket.assigns.prefix || "/"}?domain=#{AshAdmin.Domain.name(socket.assigns.domain)}&resource=#{AshAdmin.Resource.name(socket.assigns.resource)}"
|
||||
)}
|
||||
|
||||
_update ->
|
||||
|
@ -1125,7 +1125,7 @@ defmodule AshAdmin.Components.Resource.Form do
|
|||
socket
|
||||
|> redirect(
|
||||
to:
|
||||
"#{socket.assigns.prefix || "/"}?api=#{AshAdmin.Api.name(socket.assigns.api)}&resource=#{AshAdmin.Resource.name(socket.assigns.resource)}&action_type=update&tab=update&table=#{socket.assigns.table}&primary_key=#{encode_primary_key(record)}"
|
||||
"#{socket.assigns.prefix || "/"}?domain=#{AshAdmin.Domain.name(socket.assigns.domain)}&resource=#{AshAdmin.Resource.name(socket.assigns.resource)}&action_type=update&tab=update&table=#{socket.assigns.table}&primary_key=#{encode_primary_key(record)}"
|
||||
)}
|
||||
end
|
||||
end
|
||||
|
@ -1230,7 +1230,7 @@ defmodule AshAdmin.Components.Resource.Form do
|
|||
path,
|
||||
fn adding_form ->
|
||||
if adding_form.data do
|
||||
new_data = socket.assigns.api.load!(adding_form.data, relationship)
|
||||
new_data = Ash.load!(adding_form.data, relationship, domain: socket.assigns.domain)
|
||||
|
||||
if Map.has_key?(adding_form.source, :data) do
|
||||
%{adding_form | data: new_data, source: %{adding_form.source | data: new_data}}
|
||||
|
@ -1285,7 +1285,7 @@ defmodule AshAdmin.Components.Resource.Form do
|
|||
socket
|
||||
|> redirect(
|
||||
to:
|
||||
"#{socket.assigns.prefix}?api=#{AshAdmin.Api.name(socket.assigns.api)}&resource=#{AshAdmin.Resource.name(socket.assigns.resource)}"
|
||||
"#{socket.assigns.prefix}?domain=#{AshAdmin.Domain.name(socket.assigns.domain)}&resource=#{AshAdmin.Resource.name(socket.assigns.resource)}"
|
||||
)}
|
||||
|
||||
{:error, form} ->
|
||||
|
@ -1404,8 +1404,7 @@ defmodule AshAdmin.Components.Resource.Form do
|
|||
def relationships(resource, action, nil) do
|
||||
resource
|
||||
|> Ash.Resource.Info.relationships()
|
||||
|> Enum.filter(& &1.writable?)
|
||||
|> Enum.reject(& &1.private?)
|
||||
|> Enum.filter(& &1.writable? && &1.public?)
|
||||
|> only_accepted(action)
|
||||
|> sort_relationships()
|
||||
end
|
||||
|
@ -1454,20 +1453,20 @@ defmodule AshAdmin.Components.Resource.Form do
|
|||
|
||||
def attributes(resource, %{type: :destroy} = action, _) do
|
||||
action.arguments
|
||||
|> Enum.reject(& &1.private?)
|
||||
|> Enum.filter(& &1.public?)
|
||||
|> sort_attributes(resource, action)
|
||||
end
|
||||
|
||||
def attributes(resource, action, _) do
|
||||
arguments =
|
||||
action.arguments
|
||||
|> Enum.reject(& &1.private?)
|
||||
|> Enum.filter(& &1.public?)
|
||||
|
||||
attributes =
|
||||
resource
|
||||
|> Ash.Resource.Info.attributes()
|
||||
|> Enum.filter(& &1.writable?)
|
||||
|> Enum.reject(&(&1.private? || &1.name == :autogenerated_id))
|
||||
|> Enum.filter(& &1.writable? && &1.public?)
|
||||
|> Enum.reject(&(&1.name == :autogenerated_id))
|
||||
|> only_accepted(action)
|
||||
|> Enum.reject(fn attribute ->
|
||||
Enum.any?(arguments, &(&1.name == attribute.name))
|
||||
|
@ -1623,7 +1622,7 @@ defmodule AshAdmin.Components.Resource.Form do
|
|||
:create ->
|
||||
socket.assigns.resource
|
||||
|> AshPhoenix.Form.for_create(socket.assigns.action.name,
|
||||
api: socket.assigns.api,
|
||||
domain: socket.assigns.domain,
|
||||
actor: socket.assigns[:actor],
|
||||
authorize?: socket.assigns[:authorizing],
|
||||
forms: auto_forms,
|
||||
|
@ -1634,7 +1633,7 @@ defmodule AshAdmin.Components.Resource.Form do
|
|||
:update ->
|
||||
socket.assigns.record
|
||||
|> AshPhoenix.Form.for_update(socket.assigns.action.name,
|
||||
api: socket.assigns.api,
|
||||
domain: socket.assigns.domain,
|
||||
forms: auto_forms,
|
||||
actor: socket.assigns[:actor],
|
||||
authorize?: socket.assigns[:authorizing],
|
||||
|
@ -1645,7 +1644,7 @@ defmodule AshAdmin.Components.Resource.Form do
|
|||
:destroy ->
|
||||
socket.assigns.record
|
||||
|> AshPhoenix.Form.for_destroy(socket.assigns.action.name,
|
||||
api: socket.assigns.api,
|
||||
domain: socket.assigns.domain,
|
||||
forms: auto_forms,
|
||||
actor: socket.assigns[:actor],
|
||||
authorize?: socket.assigns[:authorizing],
|
||||
|
|
|
@ -5,14 +5,14 @@ defmodule AshAdmin.Components.Resource.Info do
|
|||
alias AshAdmin.Components.Resource.MetadataTable
|
||||
|
||||
attr :resource, :any, required: true
|
||||
attr :api, :any, required: true
|
||||
attr :domain, :any, required: true
|
||||
attr :prefix, :any, required: true
|
||||
|
||||
def info(assigns) do
|
||||
~H"""
|
||||
<div class="relative mx-12">
|
||||
<MetadataTable.attribute_table resource={@resource} />
|
||||
<MetadataTable.relationship_table api={@api} resource={@resource} prefix={@prefix} />
|
||||
<MetadataTable.relationship_table domain={@domain} resource={@resource} prefix={@prefix} />
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
|
|
@ -45,7 +45,7 @@ defmodule AshAdmin.Components.Resource.MetadataTable do
|
|||
</.td>
|
||||
<.td>
|
||||
<CoreComponents.icon
|
||||
name={if attribute.private?, do: "hero-check", else: "hero-x-mark"}
|
||||
name={if !attribute.public?, do: "hero-check", else: "hero-x-mark"}
|
||||
class="h-4 w-4 text-gray-500"
|
||||
/>
|
||||
</.td>
|
||||
|
@ -69,7 +69,7 @@ defmodule AshAdmin.Components.Resource.MetadataTable do
|
|||
end
|
||||
|
||||
attr :resource, :any, required: true
|
||||
attr :api, :any, required: true
|
||||
attr :domain, :any, required: true
|
||||
attr :prefix, :any, required: true
|
||||
|
||||
def relationship_table(assigns) do
|
||||
|
@ -98,7 +98,7 @@ defmodule AshAdmin.Components.Resource.MetadataTable do
|
|||
<%= relationship.type %>
|
||||
</.td>
|
||||
<.td>
|
||||
<.link navigate={"#{@prefix}?api=#{AshAdmin.Api.name(@api)}&resource=#{AshAdmin.Resource.name(relationship.destination)}"}>
|
||||
<.link navigate={"#{@prefix}?domain=#{AshAdmin.Domain.name(@domain)}&resource=#{AshAdmin.Resource.name(relationship.destination)}"}>
|
||||
<%= AshAdmin.Resource.name(relationship.destination) %>
|
||||
</.link>
|
||||
</.td>
|
||||
|
@ -157,7 +157,7 @@ defmodule AshAdmin.Components.Resource.MetadataTable do
|
|||
defp attributes(resource) do
|
||||
resource
|
||||
|> Ash.Resource.Info.attributes()
|
||||
|> Enum.sort_by(& &1.private?)
|
||||
|> Enum.sort_by(& not(&1.public?))
|
||||
end
|
||||
|
||||
defp attribute_type(attribute) do
|
||||
|
@ -173,6 +173,6 @@ defmodule AshAdmin.Components.Resource.MetadataTable do
|
|||
defp relationships(resource) do
|
||||
resource
|
||||
|> Ash.Resource.Info.relationships()
|
||||
|> Enum.sort_by(& &1.private?)
|
||||
|> Enum.sort_by(& not(&1.public?))
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,7 +4,7 @@ defmodule AshAdmin.Components.Resource.Nav do
|
|||
alias AshAdmin.Components.TopNav.Dropdown
|
||||
|
||||
attr :resource, :any, required: true
|
||||
attr :api, :any, required: true
|
||||
attr :domain, :any, required: true
|
||||
attr :tab, :string, required: true
|
||||
attr :action, :any
|
||||
attr :table, :any, default: nil
|
||||
|
@ -18,7 +18,7 @@ defmodule AshAdmin.Components.Resource.Nav do
|
|||
<div class="flex items-center w-full">
|
||||
<div class="flex-shrink-0">
|
||||
<h3 class="text-white text-lg">
|
||||
<.link navigate={"#{@prefix}?api=#{AshAdmin.Api.name(@api)}&resource=#{AshAdmin.Resource.name(@resource)}"}>
|
||||
<.link navigate={"#{@prefix}?domain=#{AshAdmin.Domain.name(@domain)}&resource=#{AshAdmin.Resource.name(@resource)}"}>
|
||||
<%= AshAdmin.Resource.name(@resource) %>
|
||||
</.link>
|
||||
</h3>
|
||||
|
@ -27,7 +27,7 @@ defmodule AshAdmin.Components.Resource.Nav do
|
|||
<div class="ml-12 flex items-center space-x-1">
|
||||
<div :if={has_create_action?(@resource)} class="relative">
|
||||
<.link
|
||||
navigate={"#{@prefix}?api=#{AshAdmin.Api.name(@api)}&resource=#{AshAdmin.Resource.name(@resource)}&action_type=create&action=#{create_action(@resource).name}&tab=create&table=#{@table}"}
|
||||
navigate={"#{@prefix}?domain=#{AshAdmin.Domain.name(@domain)}&resource=#{AshAdmin.Resource.name(@resource)}&action_type=create&action=#{create_action(@resource).name}&tab=create&table=#{@table}"}
|
||||
class="inline-flex justify-center w-full rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 focus:ring-indigo-500"
|
||||
>
|
||||
Create
|
||||
|
@ -39,7 +39,7 @@ defmodule AshAdmin.Components.Resource.Nav do
|
|||
name="Read"
|
||||
id={"#{@resource}_data_dropdown"}
|
||||
active={@tab == "data"}
|
||||
groups={data_groups(@prefix, @api, @resource, @action, @table)}
|
||||
groups={data_groups(@prefix, @domain, @resource, @action, @table)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -55,7 +55,7 @@ defmodule AshAdmin.Components.Resource.Nav do
|
|||
Enum.find(Ash.Resource.Info.actions(resource), &(&1.type == :create))
|
||||
end
|
||||
|
||||
defp data_groups(prefix, api, resource, current_action, table) do
|
||||
defp data_groups(prefix, domain, resource, current_action, table) do
|
||||
read_actions = AshAdmin.Resource.read_actions(resource)
|
||||
|
||||
[
|
||||
|
@ -66,7 +66,7 @@ defmodule AshAdmin.Components.Resource.Nav do
|
|||
%{
|
||||
text: action_name(action),
|
||||
to:
|
||||
"#{prefix}?api=#{AshAdmin.Api.name(api)}&resource=#{AshAdmin.Resource.name(resource)}&table=#{table}&action_type=read&action=#{action.name}",
|
||||
"#{prefix}?domain=#{AshAdmin.Domain.name(domain)}&resource=#{AshAdmin.Resource.name(resource)}&table=#{table}&action_type=read&action=#{action.name}",
|
||||
active: current_action == action
|
||||
}
|
||||
end)
|
||||
|
|
|
@ -8,7 +8,7 @@ defmodule AshAdmin.Components.Resource do
|
|||
|
||||
# prop hide_filter, :boolean, default: true
|
||||
attr :resource, :any, required: true
|
||||
attr :api, :any, required: true
|
||||
attr :domain, :any, required: true
|
||||
attr :tab, :string, required: true
|
||||
attr :action, :any
|
||||
attr :actor, :any, required: true
|
||||
|
@ -29,7 +29,7 @@ defmodule AshAdmin.Components.Resource do
|
|||
<div class="h-screen">
|
||||
<Nav.nav
|
||||
resource={@resource}
|
||||
api={@api}
|
||||
domain={@domain}
|
||||
tab={@tab}
|
||||
action={@action}
|
||||
table={@table}
|
||||
|
@ -50,7 +50,7 @@ defmodule AshAdmin.Components.Resource do
|
|||
url_path={@url_path}
|
||||
params={@params}
|
||||
action={@action}
|
||||
api={@api}
|
||||
domain={@domain}
|
||||
id={update_id(@resource)}
|
||||
actor={@actor}
|
||||
authorizing={@authorizing}
|
||||
|
@ -73,7 +73,7 @@ defmodule AshAdmin.Components.Resource do
|
|||
url_path={@url_path}
|
||||
action={@action}
|
||||
params={@params}
|
||||
api={@api}
|
||||
domain={@domain}
|
||||
id={destroy_id(@resource)}
|
||||
actor={@actor}
|
||||
authorizing={@authorizing}
|
||||
|
@ -87,7 +87,7 @@ defmodule AshAdmin.Components.Resource do
|
|||
:if={@tab == "show" && match?({:ok, %_{}}, @record)}
|
||||
module={Show}
|
||||
resource={@resource}
|
||||
api={@api}
|
||||
domain={@domain}
|
||||
id={show_id(@resource)}
|
||||
record={unwrap(@record)}
|
||||
actor={@actor}
|
||||
|
@ -99,7 +99,7 @@ defmodule AshAdmin.Components.Resource do
|
|||
<Info.info
|
||||
:if={@tab == "info" || (is_nil(@tab) && is_nil(@action_type))}
|
||||
resource={@resource}
|
||||
api={@api}
|
||||
domain={@domain}
|
||||
prefix={@prefix}
|
||||
/>
|
||||
<.live_component
|
||||
|
@ -109,7 +109,7 @@ defmodule AshAdmin.Components.Resource do
|
|||
resource={@resource}
|
||||
url_path={@url_path}
|
||||
params={@params}
|
||||
api={@api}
|
||||
domain={@domain}
|
||||
action={@action}
|
||||
id={create_id(@resource)}
|
||||
actor={@actor}
|
||||
|
@ -127,7 +127,7 @@ defmodule AshAdmin.Components.Resource do
|
|||
resource={@resource}
|
||||
action={@action}
|
||||
actor={@actor}
|
||||
api={@api}
|
||||
domain={@domain}
|
||||
url_path={@url_path}
|
||||
params={@params}
|
||||
id={data_table_id(@resource)}
|
||||
|
|
|
@ -9,7 +9,7 @@ defmodule AshAdmin.Components.Resource.Show do
|
|||
|
||||
attr :resource, :any
|
||||
attr :record, :any, default: nil
|
||||
attr :api, :any, default: nil
|
||||
attr :domain, :any, default: nil
|
||||
attr :action, :any
|
||||
attr :authorizing, :boolean, default: false
|
||||
attr :actor, :any
|
||||
|
@ -45,7 +45,7 @@ defmodule AshAdmin.Components.Resource.Show do
|
|||
class="float-right pt-4 pr-4"
|
||||
phx-click="set_actor"
|
||||
phx-value-resource={@resource}
|
||||
phx-value-api={@api}
|
||||
phx-value-domain={@domain}
|
||||
phx-value-pkey={encode_primary_key(@record)}
|
||||
>
|
||||
<.icon name="hero-key" class="h-5 w-5 text-gray-500" />
|
||||
|
@ -56,7 +56,7 @@ defmodule AshAdmin.Components.Resource.Show do
|
|||
<div :if={@buttons} class="px-4 py-3 text-right sm:px-6">
|
||||
<.link
|
||||
:if={destroy?(@resource)}
|
||||
navigate={"#{@prefix}?api=#{AshAdmin.Api.name(@api)}&resource=#{AshAdmin.Resource.name(@resource)}&action_type=destroy&action=#{primary_action_name(@resource, :destroy)}&tab=destroy&table=#{@table}&primary_key=#{encode_primary_key(@record)}"}
|
||||
navigate={"#{@prefix}?domain=#{AshAdmin.Domain.name(@domain)}&resource=#{AshAdmin.Resource.name(@resource)}&action_type=destroy&action=#{primary_action_name(@resource, :destroy)}&tab=destroy&table=#{@table}&primary_key=#{encode_primary_key(@record)}"}
|
||||
class="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
|
||||
>
|
||||
Destroy
|
||||
|
@ -64,7 +64,7 @@ defmodule AshAdmin.Components.Resource.Show do
|
|||
|
||||
<.link
|
||||
:if={update?(@resource)}
|
||||
navigate={"#{@prefix}?api=#{AshAdmin.Api.name(@api)}&resource=#{AshAdmin.Resource.name(@resource)}&action_type=update&action=#{primary_action_name(@resource, :update)}&tab=update&table=#{@table}&primary_key=#{encode_primary_key(@record)}"}
|
||||
navigate={"#{@prefix}?domain=#{AshAdmin.Domain.name(@domain)}&resource=#{AshAdmin.Resource.name(@resource)}&action_type=update&action=#{primary_action_name(@resource, :update)}&tab=update&table=#{@table}&primary_key=#{encode_primary_key(@record)}"}
|
||||
class="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
|
||||
>
|
||||
Update
|
||||
|
@ -131,7 +131,7 @@ defmodule AshAdmin.Components.Resource.Show do
|
|||
name: name,
|
||||
destination: destination,
|
||||
context: context,
|
||||
api: destination_api
|
||||
domain: destination_domain
|
||||
}) do
|
||||
case Map.get(record, name) do
|
||||
nil ->
|
||||
|
@ -144,7 +144,7 @@ defmodule AshAdmin.Components.Resource.Show do
|
|||
name: name,
|
||||
destination: destination,
|
||||
context: context,
|
||||
destination_api: destination_api
|
||||
destination_domain: destination_domain
|
||||
)
|
||||
|
||||
~H"""
|
||||
|
@ -153,7 +153,7 @@ defmodule AshAdmin.Components.Resource.Show do
|
|||
<div class="px-4 py-3 text-right sm:px-6">
|
||||
<.link
|
||||
:if={AshAdmin.Resource.show_action(@destination)}
|
||||
navigate={"#{@prefix}?api=#{AshAdmin.Api.name(@destination_api || @api)}&resource=#{AshAdmin.Resource.name(@destination)}&tab=show&table=#{@context[:data_layer][:table]}&primary_key=#{encode_primary_key(@record)}"}
|
||||
navigate={"#{@prefix}?domain=#{AshAdmin.Domain.name(@destination_domain || @domain)}&resource=#{AshAdmin.Resource.name(@destination)}&tab=show&table=#{@context[:data_layer][:table]}&primary_key=#{encode_primary_key(@record)}"}
|
||||
class="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
|
||||
>
|
||||
Show
|
||||
|
@ -186,7 +186,7 @@ defmodule AshAdmin.Components.Resource.Show do
|
|||
<Table.table
|
||||
data={@data}
|
||||
resource={@destination}
|
||||
api={@api}
|
||||
domain={@domain}
|
||||
table={@context[:data_layer][:table]}
|
||||
prefix={@prefix}
|
||||
skip={[@destination_attribute]}
|
||||
|
@ -470,12 +470,13 @@ defmodule AshAdmin.Components.Resource.Show do
|
|||
|
||||
def handle_event("load", %{"relationship" => relationship}, socket) do
|
||||
record = socket.assigns.record
|
||||
api = socket.assigns.api
|
||||
domain = socket.assigns.domain
|
||||
relationship = String.to_existing_atom(relationship)
|
||||
|
||||
case api.load(
|
||||
case Ash.load(
|
||||
record,
|
||||
relationship,
|
||||
domain: domain,
|
||||
actor: socket.assigns[:actor],
|
||||
authorize?: socket.assigns[:authorizing]
|
||||
) do
|
||||
|
|
|
@ -11,7 +11,7 @@ defmodule AshAdmin.Components.Resource.Table do
|
|||
attr :data, :list, default: nil
|
||||
attr :resource, :any, required: true
|
||||
attr :actions, :boolean, default: true
|
||||
attr :api, :any, required: true
|
||||
attr :domain, :any, required: true
|
||||
attr :table, :any, required: true
|
||||
attr :prefix, :any, required: true
|
||||
attr :skip, :list, default: []
|
||||
|
@ -32,7 +32,7 @@ defmodule AshAdmin.Components.Resource.Table do
|
|||
<tr :for={record <- @data} class="border-b-2">
|
||||
<td :for={attribute <- attributes(@resource, @attributes, @skip)} class="py-3">
|
||||
<%= render_attribute(
|
||||
@api,
|
||||
@domain,
|
||||
record,
|
||||
attribute,
|
||||
@format_fields,
|
||||
|
@ -43,19 +43,19 @@ defmodule AshAdmin.Components.Resource.Table do
|
|||
<td :if={@actions && actions?(@resource)}>
|
||||
<div class="flex h-max justify-items-center">
|
||||
<div :if={AshAdmin.Resource.show_action(@resource)}>
|
||||
<.link navigate={"#{@prefix}?api=#{AshAdmin.Api.name(@api)}&resource=#{AshAdmin.Resource.name(@resource)}&tab=show&table=#{@table}&primary_key=#{encode_primary_key(record)}"}>
|
||||
<.link navigate={"#{@prefix}?domain=#{AshAdmin.Domain.name(@domain)}&resource=#{AshAdmin.Resource.name(@resource)}&tab=show&table=#{@table}&primary_key=#{encode_primary_key(record)}"}>
|
||||
<.icon name="hero-information-circle-solid" class="h-5 w-5 text-gray-500" />
|
||||
</.link>
|
||||
</div>
|
||||
|
||||
<div :if={AshAdmin.Helpers.primary_action(@resource, :update)}>
|
||||
<.link navigate={"#{@prefix}?api=#{AshAdmin.Api.name(@api)}&resource=#{AshAdmin.Resource.name(@resource)}&action_type=update&action=#{AshAdmin.Helpers.primary_action(@resource, :update).name}&tab=update&table=#{@table}&primary_key=#{encode_primary_key(record)}"}>
|
||||
<.link navigate={"#{@prefix}?domain=#{AshAdmin.Domain.name(@domain)}&resource=#{AshAdmin.Resource.name(@resource)}&action_type=update&action=#{AshAdmin.Helpers.primary_action(@resource, :update).name}&tab=update&table=#{@table}&primary_key=#{encode_primary_key(record)}"}>
|
||||
<.icon name="hero-pencil-solid" class="h-5 w-5 text-gray-500" />
|
||||
</.link>
|
||||
</div>
|
||||
|
||||
<div :if={AshAdmin.Helpers.primary_action(@resource, :destroy)}>
|
||||
<.link navigate={"#{@prefix}?api=#{AshAdmin.Api.name(@api)}&resource=#{AshAdmin.Resource.name(@resource)}&action_type=destroy&action=#{AshAdmin.Helpers.primary_action(@resource, :destroy).name}&tab=destroy&table=#{@table}&primary_key=#{encode_primary_key(record)}"}>
|
||||
<.link navigate={"#{@prefix}?domain=#{AshAdmin.Domain.name(@domain)}&resource=#{AshAdmin.Resource.name(@resource)}&action_type=destroy&action=#{AshAdmin.Helpers.primary_action(@resource, :destroy).name}&tab=destroy&table=#{@table}&primary_key=#{encode_primary_key(record)}"}>
|
||||
<.icon name="hero-x-circle-solid" class="h-5 w-5 text-gray-500" />
|
||||
</.link>
|
||||
</div>
|
||||
|
@ -64,7 +64,7 @@ defmodule AshAdmin.Components.Resource.Table do
|
|||
:if={AshAdmin.Resource.actor?(@resource)}
|
||||
phx-click="set_actor"
|
||||
phx-value-resource={@resource}
|
||||
phx-value-api={@api}
|
||||
phx-value-domain={@domain}
|
||||
phx-value-pkey={encode_primary_key(record)}
|
||||
>
|
||||
<.icon name="hero-key-solid" class="h-5 w-5 text-gray-500" />
|
||||
|
@ -99,15 +99,15 @@ defmodule AshAdmin.Components.Resource.Table do
|
|||
|> Enum.reject(&(&1.name in skip))
|
||||
end
|
||||
|
||||
defp render_attribute(api, record, attribute, formats, show_sensitive_fields, actor) do
|
||||
process_attribute(api, record, attribute, formats, show_sensitive_fields, actor)
|
||||
defp render_attribute(domain, record, attribute, formats, show_sensitive_fields, actor) do
|
||||
process_attribute(domain, record, attribute, formats, show_sensitive_fields, actor)
|
||||
rescue
|
||||
_ ->
|
||||
"..."
|
||||
end
|
||||
|
||||
defp process_attribute(
|
||||
api,
|
||||
domain,
|
||||
record,
|
||||
%module{} = attribute,
|
||||
formats,
|
||||
|
@ -124,7 +124,7 @@ defmodule AshAdmin.Components.Resource.Table do
|
|||
if loaded?(record, attribute.name) do
|
||||
record
|
||||
else
|
||||
api.load!(record, [{attribute.name, display_attributes}], actor: actor)
|
||||
Ash.load!(record, [{attribute.name, display_attributes}], actor: actor, domain: domain)
|
||||
end
|
||||
|
||||
relationship = Map.get(record, attribute.name)
|
||||
|
@ -135,7 +135,7 @@ defmodule AshAdmin.Components.Resource.Table do
|
|||
attributes = attributes(attribute.destination, display_attributes, [])
|
||||
|
||||
Enum.map_join(attributes, " - ", fn x ->
|
||||
render_attribute(api, relationship, x, formats, show_sensitive_fields, actor)
|
||||
render_attribute(domain, relationship, x, formats, show_sensitive_fields, actor)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
@ -159,7 +159,7 @@ defmodule AshAdmin.Components.Resource.Table do
|
|||
end
|
||||
end
|
||||
|
||||
defp process_attribute(_api, _record, _attr, _formats, _show_sensitive_fields, _actor) do
|
||||
defp process_attribute(_domain, _record, _attr, _formats, _show_sensitive_fields, _actor) do
|
||||
"..."
|
||||
end
|
||||
|
||||
|
|
|
@ -4,10 +4,10 @@ defmodule AshAdmin.Components.TopNav do
|
|||
import Tails
|
||||
alias AshAdmin.Components.TopNav.{ActorSelect, DrawerDropdown, Dropdown, TenantForm}
|
||||
|
||||
attr :api, :any, required: true
|
||||
attr :domain, :any, required: true
|
||||
attr :resource, :any, required: true
|
||||
attr :actor_resources, :any, required: true
|
||||
attr :apis, :any, required: true
|
||||
attr :domains, :any, required: true
|
||||
attr :tenant, :any, required: true
|
||||
attr :clear_tenant, :string
|
||||
attr :set_tenant, :string
|
||||
|
@ -17,7 +17,7 @@ defmodule AshAdmin.Components.TopNav do
|
|||
attr :authorizing, :boolean, required: true
|
||||
attr :actor_paused, :boolean, required: true
|
||||
attr :actor, :any, required: true
|
||||
attr :actor_api, :any, required: true
|
||||
attr :actor_domain, :any, required: true
|
||||
attr :prefix, :any, required: true
|
||||
|
||||
def render(assigns) do
|
||||
|
@ -37,14 +37,14 @@ defmodule AshAdmin.Components.TopNav do
|
|||
<div class="flex justify-between">
|
||||
<div class="ml-10 flex items-center">
|
||||
<.live_component
|
||||
:for={api <- @apis}
|
||||
:for={domain <- @domains}
|
||||
module={Dropdown}
|
||||
active={api == @api}
|
||||
active={domain == @domain}
|
||||
class="mr-1"
|
||||
id={AshAdmin.Api.name(api) <> "_api_nav"}
|
||||
name={AshAdmin.Api.name(api)}
|
||||
groups={dropdown_groups(@prefix, @resource, api)}
|
||||
group_labels={dropdown_group_labels(api)}
|
||||
id={AshAdmin.Domain.name(domain) <> "_domain_nav"}
|
||||
name={AshAdmin.Domain.name(domain)}
|
||||
groups={dropdown_groups(@prefix, @resource, domain)}
|
||||
group_labels={dropdown_group_labels(domain)}
|
||||
/>
|
||||
</div>
|
||||
<div class="ml-10 flex items-center">
|
||||
|
@ -57,12 +57,12 @@ defmodule AshAdmin.Components.TopNav do
|
|||
toggle_authorizing={@toggle_authorizing}
|
||||
toggle_actor_paused={@toggle_actor_paused}
|
||||
clear_actor={@clear_actor}
|
||||
actor_api={@actor_api}
|
||||
api={@api}
|
||||
actor_domain={@actor_domain}
|
||||
domain={@domain}
|
||||
prefix={@prefix}
|
||||
/>
|
||||
<TenantForm.tenant_form
|
||||
:if={show_tenant_form?(@apis)}
|
||||
:if={show_tenant_form?(@domains)}
|
||||
tenant={@tenant}
|
||||
editing_tenant={@editing_tenant}
|
||||
set_tenant={@set_tenant}
|
||||
|
@ -111,14 +111,14 @@ defmodule AshAdmin.Components.TopNav do
|
|||
toggle_authorizing={@toggle_authorizing}
|
||||
toggle_actor_paused={@toggle_actor_paused}
|
||||
clear_actor={@clear_actor}
|
||||
actor_api={@actor_api}
|
||||
api={@api}
|
||||
actor_domain={@actor_domain}
|
||||
domain={@domain}
|
||||
prefix={@prefix}
|
||||
/>
|
||||
</div>
|
||||
<div class="block px-4 py-2 text-sm">
|
||||
<.live_component
|
||||
:if={show_tenant_form?(@apis)}
|
||||
:if={show_tenant_form?(@domains)}
|
||||
module={TenantForm}
|
||||
tenant={@tenant}
|
||||
id="tenant_editor_drawer"
|
||||
|
@ -127,12 +127,12 @@ defmodule AshAdmin.Components.TopNav do
|
|||
/>
|
||||
</div>
|
||||
<.live_component
|
||||
:for={api <- @apis}
|
||||
:for={domain <- @domains}
|
||||
module={DrawerDropdown}
|
||||
id={AshAdmin.Api.name(api) <> "_api_nav_drawer"}
|
||||
name={AshAdmin.Api.name(api)}
|
||||
groups={dropdown_groups(@prefix, @resource, api)}
|
||||
group_labels={dropdown_group_labels(api)}
|
||||
id={AshAdmin.Domain.name(domain) <> "_domain_nav_drawer"}
|
||||
name={AshAdmin.Domain.name(domain)}
|
||||
groups={dropdown_groups(@prefix, @resource, domain)}
|
||||
group_labels={dropdown_group_labels(domain)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -140,12 +140,12 @@ defmodule AshAdmin.Components.TopNav do
|
|||
"""
|
||||
end
|
||||
|
||||
defp dropdown_groups(prefix, current_resource, api) do
|
||||
for resource <- Ash.Api.Info.resources(api) do
|
||||
defp dropdown_groups(prefix, current_resource, domain) do
|
||||
for resource <- Ash.Domain.Info.resources(domain) do
|
||||
%{
|
||||
text: AshAdmin.Resource.name(resource),
|
||||
to:
|
||||
"#{prefix}?api=#{AshAdmin.Api.name(api)}&resource=#{AshAdmin.Resource.name(resource)}",
|
||||
"#{prefix}?domain=#{AshAdmin.Domain.name(domain)}&resource=#{AshAdmin.Resource.name(resource)}",
|
||||
active: resource == current_resource,
|
||||
group: AshAdmin.Resource.resource_group(resource)
|
||||
}
|
||||
|
@ -155,8 +155,8 @@ defmodule AshAdmin.Components.TopNav do
|
|||
|> Keyword.values()
|
||||
end
|
||||
|
||||
defp dropdown_group_labels(api) do
|
||||
AshAdmin.Api.resource_group_labels(api)
|
||||
defp dropdown_group_labels(domain) do
|
||||
AshAdmin.Domain.resource_group_labels(domain)
|
||||
end
|
||||
|
||||
def mount(socket) do
|
||||
|
@ -175,10 +175,10 @@ defmodule AshAdmin.Components.TopNav do
|
|||
{:noreply, assign(socket, :open, !socket.assigns.open)}
|
||||
end
|
||||
|
||||
defp show_tenant_form?(apis) do
|
||||
Enum.any?(apis, fn api ->
|
||||
api
|
||||
|> Ash.Api.Info.resources()
|
||||
defp show_tenant_form?(domains) do
|
||||
Enum.any?(domains, fn domain ->
|
||||
domain
|
||||
|> Ash.Domain.Info.resources()
|
||||
|> Enum.any?(fn resource ->
|
||||
Ash.Resource.Info.multitenancy_strategy(resource)
|
||||
end)
|
||||
|
|
|
@ -11,8 +11,8 @@ defmodule AshAdmin.Components.TopNav.ActorSelect do
|
|||
attr :toggle_authorizing, :string, required: true
|
||||
attr :toggle_actor_paused, :string, required: true
|
||||
attr :clear_actor, :string, required: true
|
||||
attr :api, :any, required: true
|
||||
attr :actor_api, :any, required: true
|
||||
attr :domain, :any, required: true
|
||||
attr :actor_domain, :any, required: true
|
||||
attr :prefix, :any, required: true
|
||||
|
||||
def actor_select(assigns) do
|
||||
|
@ -73,7 +73,7 @@ defmodule AshAdmin.Components.TopNav.ActorSelect do
|
|||
<.link
|
||||
:if={@actor}
|
||||
class="hover:text-blue-400 hover:underline"
|
||||
target={"#{@prefix}?api=#{AshAdmin.Api.name(@actor_api)}&resource=#{AshAdmin.Resource.name(@actor.__struct__)}&tab=show&primary_key=#{encode_primary_key(@actor)}"}
|
||||
target={"#{@prefix}?domain=#{AshAdmin.Domain.name(@actor_domain)}&resource=#{AshAdmin.Resource.name(@actor.__struct__)}&tab=show&primary_key=#{encode_primary_key(@actor)}"}
|
||||
>
|
||||
<%= user_display(@actor) %>
|
||||
</.link>
|
||||
|
@ -104,27 +104,27 @@ defmodule AshAdmin.Components.TopNav.ActorSelect do
|
|||
"""
|
||||
end
|
||||
|
||||
defp render_actor_link(assigns, [{api, resource}]) do
|
||||
assigns = assign(assigns, api: api, resource: resource)
|
||||
defp render_actor_link(assigns, [{domain, resource}]) do
|
||||
assigns = assign(assigns, domain: domain, resource: resource)
|
||||
|
||||
~H"""
|
||||
<.link navigate={"#{@prefix}?api=#{AshAdmin.Api.name(@api)}&resource=#{AshAdmin.Resource.name(@resource)}&action_type=read"}>
|
||||
<.link navigate={"#{@prefix}?domain=#{AshAdmin.Domain.name(@domain)}&resource=#{AshAdmin.Resource.name(@resource)}&action_type=read"}>
|
||||
Set <%= AshAdmin.Resource.name(@resource) %>
|
||||
</.link>
|
||||
"""
|
||||
end
|
||||
|
||||
defp render_actor_link(assigns, apis_and_resources) do
|
||||
assigns = assign(assigns, apis_and_resources: apis_and_resources)
|
||||
defp render_actor_link(assigns, domains_and_resources) do
|
||||
assigns = assign(assigns, domains_and_resources: domains_and_resources)
|
||||
|
||||
~H"""
|
||||
<div aria-labelledby="actor-banner">
|
||||
<.link
|
||||
:for={{{api, resource}, i} <- Enum.with_index(@apis_and_resources)}
|
||||
navigate={"#{@prefix}?api=#{AshAdmin.Api.name(api)}&resource=#{AshAdmin.Resource.name(resource)}&action_type=read"}
|
||||
:for={{{domain, resource}, i} <- Enum.with_index(@domains_and_resources)}
|
||||
navigate={"#{@prefix}?domain=#{AshAdmin.Domain.name(domain)}&resource=#{AshAdmin.Resource.name(resource)}&action_type=read"}
|
||||
>
|
||||
Set <%= AshAdmin.Resource.name(resource) %>
|
||||
<span :if={i != Enum.count(@apis_and_resources) - 1}>
|
||||
<span :if={i != Enum.count(@domains_and_resources) - 1}>
|
||||
|
|
||||
</span>
|
||||
</.link>
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
defmodule AshAdmin.Api do
|
||||
defmodule AshAdmin.Domain do
|
||||
@admin %Spark.Dsl.Section{
|
||||
describe: "Configure the admin dashboard for a given API.",
|
||||
describe: "Configure the admin dashboard for a given domain.",
|
||||
name: :admin,
|
||||
schema: [
|
||||
name: [
|
||||
type: :string,
|
||||
doc: "The name of the API in the dashboard. Will be derived if not set."
|
||||
doc: "The name of the domain in the dashboard. Will be derived if not set."
|
||||
],
|
||||
show?: [
|
||||
type: :boolean,
|
||||
default: false,
|
||||
doc:
|
||||
"Whether or not this API and its resources should be included in the admin dashboard."
|
||||
"Whether or not this domain and its resources should be included in the admin dashboard."
|
||||
],
|
||||
default_resource_page: [
|
||||
type: {:in, [:schema, :primary_read]},
|
||||
|
@ -31,30 +31,30 @@ defmodule AshAdmin.Api do
|
|||
use Spark.Dsl.Extension, sections: [@admin]
|
||||
|
||||
@moduledoc """
|
||||
An API extension to alter the behavior of an API in the admin UI.
|
||||
A domain extension to alter the behavior of a domain in the admin UI.
|
||||
"""
|
||||
|
||||
def name(api) do
|
||||
Spark.Dsl.Extension.get_opt(api, [:admin], :name, nil, true) || default_name(api)
|
||||
def name(domain) do
|
||||
Spark.Dsl.Extension.get_opt(domain, [:admin], :name, nil, true) || default_name(domain)
|
||||
end
|
||||
|
||||
def show?(api) do
|
||||
Spark.Dsl.Extension.get_opt(api, [:admin], :show?, false, true)
|
||||
def show?(domain) do
|
||||
Spark.Dsl.Extension.get_opt(domain, [:admin], :show?, false, true)
|
||||
end
|
||||
|
||||
def default_resource_page(api) do
|
||||
Spark.Dsl.Extension.get_opt(api, [:admin], :default_resource_page, :schema, true)
|
||||
def default_resource_page(domain) do
|
||||
Spark.Dsl.Extension.get_opt(domain, [:admin], :default_resource_page, :schema, true)
|
||||
end
|
||||
|
||||
def resource_group_labels(api) do
|
||||
Spark.Dsl.Extension.get_opt(api, [:admin], :resource_group_labels, [], true)
|
||||
def resource_group_labels(domain) do
|
||||
Spark.Dsl.Extension.get_opt(domain, [:admin], :resource_group_labels, [], true)
|
||||
end
|
||||
|
||||
defp default_name(api) do
|
||||
split = api |> Module.split()
|
||||
defp default_name(domain) do
|
||||
split = domain |> Module.split()
|
||||
|
||||
case List.last(split) do
|
||||
"Api" ->
|
||||
"Domain" ->
|
||||
Enum.at(split, -2)
|
||||
|
||||
last ->
|
|
@ -39,20 +39,20 @@ defmodule AshAdmin.PageLive do
|
|||
|
||||
socket = assign(socket, :prefix, prefix)
|
||||
|
||||
apis = apis(otp_app)
|
||||
domains = domains(otp_app)
|
||||
|
||||
{:ok,
|
||||
socket
|
||||
|> assign(:prefix, prefix)
|
||||
|> assign(:primary_key, nil)
|
||||
|> assign(:record, nil)
|
||||
|> assign(:apis, apis)
|
||||
|> assign(:domains, domains)
|
||||
|> assign(:tenant, session["tenant"])
|
||||
|> assign(:editing_tenant, false)
|
||||
|> then(fn socket ->
|
||||
assign(socket, AshAdmin.ActorPlug.actor_assigns(socket, session))
|
||||
end)
|
||||
|> assign_new(:actor_api, fn -> nil end)
|
||||
|> assign_new(:actor_domain, fn -> nil end)
|
||||
|> assign_new(:actor_resources, fn -> [] end)
|
||||
|> assign_new(:authorizing, fn -> true end)
|
||||
|> assign_new(:actor_paused, fn -> false end)}
|
||||
|
@ -64,10 +64,10 @@ defmodule AshAdmin.PageLive do
|
|||
<.live_component
|
||||
module={TopNav}
|
||||
id="top_nav"
|
||||
apis={@apis}
|
||||
api={@api}
|
||||
domains={@domains}
|
||||
domain={@domain}
|
||||
editing_tenant={@editing_tenant}
|
||||
actor_api={@actor_api}
|
||||
actor_domain={@actor_domain}
|
||||
resource={@resource}
|
||||
tenant={@tenant}
|
||||
actor_resources={@actor_resources}
|
||||
|
@ -89,7 +89,7 @@ defmodule AshAdmin.PageLive do
|
|||
set_actor="set_actor"
|
||||
primary_key={@primary_key}
|
||||
record={@record}
|
||||
api={@api}
|
||||
domain={@domain}
|
||||
tab={@tab}
|
||||
action_type={@action_type}
|
||||
url_path={@url_path}
|
||||
|
@ -106,28 +106,28 @@ defmodule AshAdmin.PageLive do
|
|||
"""
|
||||
end
|
||||
|
||||
defp apis(otp_app) do
|
||||
defp domains(otp_app) do
|
||||
otp_app
|
||||
|> Application.get_env(:ash_apis)
|
||||
|> Enum.filter(&AshAdmin.Api.show?/1)
|
||||
|> Application.get_env(:ash_domains)
|
||||
|> Enum.filter(&AshAdmin.Domain.show?/1)
|
||||
end
|
||||
|
||||
defp assign_api(socket, api) do
|
||||
api =
|
||||
Enum.find(socket.assigns.apis, fn shown_api ->
|
||||
AshAdmin.Api.name(shown_api) == api
|
||||
end) || Enum.at(socket.assigns.apis, 0)
|
||||
defp assign_domain(socket, domain) do
|
||||
domain =
|
||||
Enum.find(socket.assigns.domains, fn shown_domain ->
|
||||
AshAdmin.Domain.name(shown_domain) == domain
|
||||
end) || Enum.at(socket.assigns.domains, 0)
|
||||
|
||||
assign(socket, :api, api)
|
||||
assign(socket, :domain, domain)
|
||||
end
|
||||
|
||||
defp assign_resource(socket, resource) do
|
||||
if socket.assigns.api do
|
||||
resources = Ash.Api.Info.resources(socket.assigns.api)
|
||||
if socket.assigns.domain do
|
||||
resources = Ash.Domain.Info.resources(socket.assigns.domain)
|
||||
|
||||
resource =
|
||||
Enum.find(resources, fn api_resource ->
|
||||
AshAdmin.Resource.name(api_resource) == resource
|
||||
Enum.find(resources, fn domain_resources ->
|
||||
AshAdmin.Resource.name(domain_resources) == resource
|
||||
end) || Enum.at(resources, 0)
|
||||
|
||||
assign(socket, :resource, resource)
|
||||
|
@ -139,7 +139,7 @@ defmodule AshAdmin.PageLive do
|
|||
defp assign_action(socket, action, action_type) do
|
||||
requested_action = action
|
||||
|
||||
if socket.assigns.api && socket.assigns.resource do
|
||||
if socket.assigns.domain && socket.assigns.resource do
|
||||
action_type =
|
||||
case action_type do
|
||||
"read" ->
|
||||
|
@ -155,7 +155,7 @@ defmodule AshAdmin.PageLive do
|
|||
:destroy
|
||||
|
||||
nil ->
|
||||
if AshAdmin.Api.default_resource_page(socket.assigns.api) == :primary_read,
|
||||
if AshAdmin.Domain.default_resource_page(socket.assigns.domain) == :primary_read,
|
||||
do: :read,
|
||||
else: nil
|
||||
end
|
||||
|
@ -242,7 +242,7 @@ defmodule AshAdmin.PageLive do
|
|||
if socket.assigns.resource do
|
||||
tables =
|
||||
if socket.assigns.resource do
|
||||
AshAdmin.Resource.polymorphic_tables(socket.assigns.resource, socket.assigns.apis)
|
||||
AshAdmin.Resource.polymorphic_tables(socket.assigns.resource, socket.assigns.domains)
|
||||
else
|
||||
[]
|
||||
end
|
||||
|
@ -271,7 +271,7 @@ defmodule AshAdmin.PageLive do
|
|||
|
||||
socket =
|
||||
socket
|
||||
|> assign_api(params["api"])
|
||||
|> assign_domain(params["domain"])
|
||||
|> assign_resource(params["resource"])
|
||||
|> assign_action(params["action"], params["action_type"])
|
||||
|> assign_tables(params["table"])
|
||||
|
@ -298,15 +298,16 @@ defmodule AshAdmin.PageLive do
|
|||
actor: actor,
|
||||
authorize?: socket.assigns.authorizing
|
||||
)
|
||||
|> socket.assigns.api.read_one()
|
||||
|> Ash.read_one(domain: socket.assigns.domain)
|
||||
|
||||
record =
|
||||
socket.assigns.resource
|
||||
|> to_one_relationships(socket.assigns.api)
|
||||
|> to_one_relationships(socket.assigns.domain)
|
||||
|> Enum.reduce(record, fn
|
||||
rel, {:ok, record} ->
|
||||
case socket.assigns.api.load(record, rel,
|
||||
case Ash.load(record, rel,
|
||||
actor: actor,
|
||||
domain: socket.assigns.domain,
|
||||
authorize?: socket.assigns.authorizing
|
||||
) do
|
||||
{:ok, record} ->
|
||||
|
@ -345,12 +346,12 @@ defmodule AshAdmin.PageLive do
|
|||
|> assign(:params, params)}
|
||||
end
|
||||
|
||||
defp to_one_relationships(resource, api) do
|
||||
defp to_one_relationships(resource, domain) do
|
||||
resource
|
||||
|> Ash.Resource.Info.relationships()
|
||||
|> Enum.filter(fn relationship ->
|
||||
api = relationship.api || api
|
||||
AshAdmin.Api.show?(api) && relationship.cardinality == :one
|
||||
domain = relationship.domain || domain || Ash.Resource.Info.domain(relationship.destination)
|
||||
AshAdmin.Domain.show?(domain) && relationship.cardinality == :one
|
||||
end)
|
||||
|> Enum.map(& &1.name)
|
||||
end
|
||||
|
@ -391,23 +392,23 @@ defmodule AshAdmin.PageLive do
|
|||
|
||||
def handle_event(
|
||||
"set_actor",
|
||||
%{"resource" => resource, "api" => api, "pkey" => primary_key},
|
||||
%{"resource" => resource, "domain" => domain, "pkey" => primary_key},
|
||||
socket
|
||||
)
|
||||
when not is_nil(resource) and not is_nil(api) do
|
||||
when not is_nil(resource) and not is_nil(domain) do
|
||||
resource = Module.concat([resource])
|
||||
|
||||
case decode_primary_key(resource, primary_key) do
|
||||
{:ok, pkey_filter} ->
|
||||
api = Module.concat([api])
|
||||
domain = Module.concat([domain])
|
||||
action = AshAdmin.Helpers.primary_action(resource, :read)
|
||||
|
||||
actor =
|
||||
resource
|
||||
|> Ash.Query.filter(^pkey_filter)
|
||||
|> api.read_one!(action: action, authorize?: false)
|
||||
|> Ash.read_one!(action: action, authorize?: false, domain: domain)
|
||||
|
||||
api_name = AshAdmin.Api.name(api)
|
||||
domain_name = AshAdmin.Domain.name(domain)
|
||||
resource_name = AshAdmin.Resource.name(resource)
|
||||
|
||||
{:noreply,
|
||||
|
@ -418,10 +419,10 @@ defmodule AshAdmin.PageLive do
|
|||
resource: to_string(resource_name),
|
||||
primary_key: encode_primary_key(actor),
|
||||
action: to_string(action.name),
|
||||
api: to_string(api_name)
|
||||
domain: to_string(domain_name)
|
||||
}
|
||||
)
|
||||
|> assign(actor: actor, actor_api: api)}
|
||||
|> assign(actor: actor, actor_domain: domain)}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ defmodule AshAdmin.Resource do
|
|||
type: {:list, :string},
|
||||
doc: """
|
||||
For resources that use ash_postgres' polymorphism capabilities, you can provide a list of tables that should be available to
|
||||
select. These will be added to the list of derivable tables based on scanning all APIs and resources provided to ash_admin.
|
||||
select. These will be added to the list of derivable tables based on scanning all domains and resources provided to ash_admin.
|
||||
"""
|
||||
],
|
||||
polymorphic_actions: [
|
||||
|
@ -98,17 +98,17 @@ defmodule AshAdmin.Resource do
|
|||
transformers: [AshAdmin.Resource.Transformers.ValidateTableColumns]
|
||||
|
||||
@moduledoc """
|
||||
An API extension to alter the behaviour of a resource in the admin UI.
|
||||
A resource extension to alter the behaviour of a resource in the admin UI.
|
||||
"""
|
||||
|
||||
def polymorphic?(resource, apis) do
|
||||
polymorphic_tables(resource, apis) not in [nil, []]
|
||||
def polymorphic?(resource, domains) do
|
||||
polymorphic_tables(resource, domains) not in [nil, []]
|
||||
end
|
||||
|
||||
def polymorphic_tables(resource, apis) do
|
||||
def polymorphic_tables(resource, domains) do
|
||||
resource
|
||||
|> Spark.Dsl.Extension.get_opt([:admin], :polymorphic_tables, [], true)
|
||||
|> Enum.concat(find_polymorphic_tables(resource, apis))
|
||||
|> Enum.concat(find_polymorphic_tables(resource, domains))
|
||||
|> Enum.uniq()
|
||||
end
|
||||
|
||||
|
@ -187,9 +187,9 @@ defmodule AshAdmin.Resource do
|
|||
end)
|
||||
end
|
||||
|
||||
defp find_polymorphic_tables(resource, apis) do
|
||||
apis
|
||||
|> Enum.flat_map(&Ash.Api.Info.resources/1)
|
||||
defp find_polymorphic_tables(resource, domains) do
|
||||
domains
|
||||
|> Enum.flat_map(&Ash.Domain.Info.resources/1)
|
||||
|> Enum.flat_map(&Ash.Resource.Info.relationships/1)
|
||||
|> Enum.filter(&(&1.destination == resource))
|
||||
|> Enum.map(& &1.context[:data_layer][:table])
|
||||
|
|
|
@ -120,7 +120,7 @@ defmodule AshAdmin.Router do
|
|||
"actor_resource",
|
||||
"actor_primary_key",
|
||||
"actor_action",
|
||||
"actor_api",
|
||||
"actor_domain",
|
||||
"actor_authorizing",
|
||||
"actor_paused"
|
||||
]
|
||||
|
|
|
@ -7,7 +7,7 @@ defmodule AshAdmin.SessionPlug do
|
|||
"actor_resource",
|
||||
"actor_primary_key",
|
||||
"actor_action",
|
||||
"actor_api",
|
||||
"actor_domain",
|
||||
"actor_authorizing",
|
||||
"actor_paused"
|
||||
]
|
||||
|
|
17
mix.exs
17
mix.exs
|
@ -61,7 +61,7 @@ defmodule AshAdmin.MixProject do
|
|||
logo: "logos/small-logo.png",
|
||||
extras: [
|
||||
"README.md",
|
||||
"documentation/dsls/DSL:-AshAdmin.Api.md",
|
||||
"documentation/dsls/DSL:-AshAdmin.Domain.md",
|
||||
"documentation/dsls/DSL:-AshAdmin.Resource.md"
|
||||
],
|
||||
groups_for_extras: [
|
||||
|
@ -76,7 +76,7 @@ defmodule AshAdmin.MixProject do
|
|||
defp aliases() do
|
||||
[
|
||||
generate_migrations:
|
||||
"ash_postgres.generate_migrations --apis Demo.Accounts.Api,Demo.Tickets.Api --snapshot-path dev/resource_snapshots --migration-path dev --drop-columns",
|
||||
"ash_postgres.generate_migrations --domains Demo.Accounts.Domain,Demo.Tickets.Domain --snapshot-path dev/resource_snapshots --migration-path dev --drop-columns",
|
||||
credo: "credo --strict",
|
||||
migrate: "ash_postgres.migrate --migrations-path dev/repo/migrations",
|
||||
migrate_tenants: "ash_postgres.migrate --migrations-path dev/repo/tenant_migrations",
|
||||
|
@ -91,13 +91,13 @@ defmodule AshAdmin.MixProject do
|
|||
"spark.cheat_sheets_in_search"
|
||||
],
|
||||
test: ["setup", "test"],
|
||||
"spark.formatter": "spark.formatter --extensions AshAdmin.Api,AshAdmin.Resource",
|
||||
"spark.formatter": "spark.formatter --extensions AshAdmin.Domain,AshAdmin.Resource",
|
||||
"assets.setup": ["tailwind.install --if-missing", "esbuild.install --if-missing"],
|
||||
"assets.build": ["tailwind default", "esbuild default"],
|
||||
"assets.deploy": ["tailwind default --minify", "esbuild default --minify", "phx.digest"],
|
||||
"spark.cheat_sheets_in_search":
|
||||
"spark.cheat_sheets_in_search --extensions AshAdmin.Api,AshAdmin.Resource",
|
||||
"spark.cheat_sheets": "spark.cheat_sheets --extensions AshAdmin.Api,AshAdmin.Resource"
|
||||
"spark.cheat_sheets_in_search --extensions AshAdmin.Domain,AshAdmin.Resource",
|
||||
"spark.cheat_sheets": "spark.cheat_sheets --extensions AshAdmin.Domain,AshAdmin.Resource"
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -112,8 +112,8 @@ defmodule AshAdmin.MixProject do
|
|||
# Run "mix help deps" to learn about dependencies.
|
||||
defp deps do
|
||||
[
|
||||
{:ash, "~> 2.0"},
|
||||
{:ash_phoenix, "~> 1.1"},
|
||||
{:ash, "~> 3.0.0-rc.0"},
|
||||
{:ash_phoenix, "~> 2.0-rc.0"},
|
||||
{:phoenix_view, "~> 2.0"},
|
||||
{:phoenix, "~> 1.7"},
|
||||
{:phoenix_live_view, "~> 0.19"},
|
||||
|
@ -122,11 +122,12 @@ defmodule AshAdmin.MixProject do
|
|||
{:tails, "~> 0.1"},
|
||||
{:gettext, "~> 0.20"},
|
||||
# Dev dependencies
|
||||
{:simple_sat, "~> 0.1", only: [:dev, :test]},
|
||||
{:esbuild, "~> 0.7", only: [:dev, :test]},
|
||||
{:tailwind, "~> 0.2.0", only: [:dev, :test]},
|
||||
{:plug_cowboy, "~> 2.0", only: [:dev, :test]},
|
||||
{:phoenix_live_reload, "~> 1.2", only: [:dev, :test]},
|
||||
{:ash_postgres, "~> 1.0"},
|
||||
{:ash_postgres, "~> 2.0-rc.0"},
|
||||
{:git_ops, "~> 2.4", only: [:dev, :test]},
|
||||
{:ex_doc, "~> 0.23", only: [:dev, :test], runtime: false},
|
||||
{:ex_check, "~> 0.14", only: [:dev, :test]},
|
||||
|
|
38
mix.lock
38
mix.lock
|
@ -1,7 +1,7 @@
|
|||
%{
|
||||
"ash": {:hex, :ash, "2.20.2", "fe0f948c22d00981826473e18cfef56b36d6761e0bf5f0079e7a5f46c8313be1", [:mix], [{:comparable, "~> 1.0", [hex: :comparable, repo: "hexpm", optional: false]}, {:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:earmark, "~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:ecto, "~> 3.7", [hex: :ecto, repo: "hexpm", optional: false]}, {:ets, "~> 0.8", [hex: :ets, repo: "hexpm", optional: false]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: false]}, {:picosat_elixir, "~> 0.2", [hex: :picosat_elixir, repo: "hexpm", optional: false]}, {:plug, ">= 0.0.0", [hex: :plug, repo: "hexpm", optional: true]}, {:reactor, "~> 0.6", [hex: :reactor, repo: "hexpm", optional: false]}, {:spark, ">= 1.1.55 and < 2.0.0-0", [hex: :spark, repo: "hexpm", optional: false]}, {:stream_data, "~> 0.6", [hex: :stream_data, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.1", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a845c9924ae4d37cfa0cc5c86227196f3f244336376507565f3a081eecdeae3e"},
|
||||
"ash_phoenix": {:hex, :ash_phoenix, "1.3.4", "8b38b5822cb68e1b8a1e9ccf947331318fcb7e8df53da841b229b3305aa6c0dd", [:mix], [{:ash, "~> 2.16", [hex: :ash, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.5.6 or ~> 1.6", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.20.3", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}], "hexpm", "3d13fe54887c84cd89c7106aa05b7bbc87498b2da53e055b21ae21173fb59823"},
|
||||
"ash_postgres": {:hex, :ash_postgres, "1.5.19", "fa4fd9fda59891774837a1c81b03cc96a7bbb220fb4471c90d7948ba4c315af4", [:mix], [{:ash, ">= 2.19.6 and < 3.0.0-0", [hex: :ash, repo: "hexpm", optional: false]}, {:ecto, "~> 3.9", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "~> 3.9", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, ">= 0.0.0", [hex: :postgrex, repo: "hexpm", optional: false]}], "hexpm", "54469ee1ca9edc5916725a2b5c46bef9307321c8ef3b6eaed573e3fa47647c5f"},
|
||||
"ash": {:hex, :ash, "3.0.0-rc.3", "9d2af1a4baef19ef0ef8a7f4bbdbbd640d54d62b484cdfd42e583d88c566115f", [:mix], [{:comparable, "~> 1.0", [hex: :comparable, repo: "hexpm", optional: false]}, {:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.7", [hex: :ecto, repo: "hexpm", optional: false]}, {:ets, "~> 0.8", [hex: :ets, repo: "hexpm", optional: false]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: false]}, {:picosat_elixir, "~> 0.2", [hex: :picosat_elixir, repo: "hexpm", optional: true]}, {:plug, ">= 0.0.0", [hex: :plug, repo: "hexpm", optional: true]}, {:reactor, "~> 0.8", [hex: :reactor, repo: "hexpm", optional: false]}, {:simple_sat, ">= 0.1.1 and < 1.0.0-0", [hex: :simple_sat, repo: "hexpm", optional: true]}, {:spark, ">= 2.1.7 and < 3.0.0-0", [hex: :spark, repo: "hexpm", optional: false]}, {:splode, "~> 0.2", [hex: :splode, repo: "hexpm", optional: false]}, {:stream_data, "~> 0.6", [hex: :stream_data, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.1", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "83a16dace30aabb1f623e6f1b405cfe1af14f87a1411b1af9bbc745cd968a373"},
|
||||
"ash_phoenix": {:hex, :ash_phoenix, "2.0.0-rc.1", "1e147bbf7d9ea077283ec7f8eef74e4c965cb524c773a691f3c79d87ca1ede0c", [:mix], [{:ash, "~> 3.0.0-rc.0", [hex: :ash, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.5.6 or ~> 1.6", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.20.3", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}], "hexpm", "387b6c35c2b35b5b114306dec7095ca5d3fab94df03b30ad58bb69f8ea61e609"},
|
||||
"ash_postgres": {:hex, :ash_postgres, "2.0.0-rc.2", "440760839f56c96c1e351056c724fd5464783d6ea3efeb980ce0875b57b20b7d", [:mix], [{:ash, "~> 3.0.0-rc.0", [hex: :ash, repo: "hexpm", optional: false]}, {:ecto, "~> 3.9", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "~> 3.9", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, ">= 0.0.0", [hex: :postgrex, repo: "hexpm", optional: false]}], "hexpm", "d8c7182e24a235980b11b6047ee77fa2e0072b5352a37e60063dee4c91d746e7"},
|
||||
"bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"},
|
||||
"castore": {:hex, :castore, "1.0.6", "ffc42f110ebfdafab0ea159cd43d31365fa0af0ce4a02ecebf1707ae619ee727", [:mix], [], "hexpm", "374c6e7ca752296be3d6780a6d5b922854ffcc74123da90f2f328996b962d33a"},
|
||||
"comparable": {:hex, :comparable, "1.0.0", "bb669e91cedd14ae9937053e5bcbc3c52bb2f22422611f43b6e38367d94a495f", [:mix], [{:typable, "~> 0.1", [hex: :typable, repo: "hexpm", optional: false]}], "hexpm", "277c11eeb1cd726e7cd41c6c199e7e52fa16ee6830b45ad4cdc62e51f62eb60c"},
|
||||
|
@ -11,7 +11,7 @@
|
|||
"credo": {:hex, :credo, "1.7.5", "643213503b1c766ec0496d828c90c424471ea54da77c8a168c725686377b9545", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "f799e9b5cd1891577d8c773d245668aa74a2fcd15eb277f51a0131690ebfb3fd"},
|
||||
"db_connection": {:hex, :db_connection, "2.6.0", "77d835c472b5b67fc4f29556dee74bf511bbafecdcaf98c27d27fa5918152086", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c2f992d15725e721ec7fbc1189d4ecdb8afef76648c746a8e1cad35e3b8a35f3"},
|
||||
"decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"},
|
||||
"dialyxir": {:hex, :dialyxir, "1.4.2", "764a6e8e7a354f0ba95d58418178d486065ead1f69ad89782817c296d0d746a5", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "516603d8067b2fd585319e4b13d3674ad4f314a5902ba8130cd97dc902ce6bbd"},
|
||||
"dialyxir": {:hex, :dialyxir, "1.4.3", "edd0124f358f0b9e95bfe53a9fcf806d615d8f838e2202a9f430d59566b6b53b", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "bf2cfb75cd5c5006bec30141b131663299c661a864ec7fbbc72dfa557487a986"},
|
||||
"earmark": {:hex, :earmark, "1.4.46", "8c7287bd3137e99d26ae4643e5b7ef2129a260e3dcf41f251750cb4563c8fb81", [:mix], [], "hexpm", "798d86db3d79964e759ddc0c077d5eb254968ed426399fbf5a62de2b5ff8910a"},
|
||||
"earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"},
|
||||
"ecto": {:hex, :ecto, "3.11.2", "e1d26be989db350a633667c5cda9c3d115ae779b66da567c68c80cfb26a8c9ee", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3c38bca2c6f8d8023f2145326cc8a80100c3ffe4dcbd9842ff867f7fc6156c65"},
|
||||
|
@ -20,27 +20,27 @@
|
|||
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
|
||||
"esbuild": {:hex, :esbuild, "0.8.1", "0cbf919f0eccb136d2eeef0df49c4acf55336de864e63594adcea3814f3edf41", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "25fc876a67c13cb0a776e7b5d7974851556baeda2085296c14ab48555ea7560f"},
|
||||
"ets": {:hex, :ets, "0.9.0", "79c6a6c205436780486f72d84230c6cba2f8a9920456750ddd1e47389107d5fd", [:mix], [], "hexpm", "2861fdfb04bcaeff370f1a5904eec864f0a56dcfebe5921ea9aadf2a481c822b"},
|
||||
"ex_check": {:hex, :ex_check, "0.15.0", "074b94c02de11c37bba1ca82ae5cc4926e6ccee862e57a485b6ba60fca2d8dc1", [:mix], [], "hexpm", "33848031a0c7e4209c3b4369ce154019788b5219956220c35ca5474299fb6a0e"},
|
||||
"ex_doc": {:hex, :ex_doc, "0.31.1", "8a2355ac42b1cc7b2379da9e40243f2670143721dd50748bf6c3b1184dae2089", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.1", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "3178c3a407c557d8343479e1ff117a96fd31bafe52a039079593fb0524ef61b0"},
|
||||
"ex_check": {:hex, :ex_check, "0.16.0", "07615bef493c5b8d12d5119de3914274277299c6483989e52b0f6b8358a26b5f", [:mix], [], "hexpm", "4d809b72a18d405514dda4809257d8e665ae7cf37a7aee3be6b74a34dec310f5"},
|
||||
"ex_doc": {:hex, :ex_doc, "0.31.2", "8b06d0a5ac69e1a54df35519c951f1f44a7b7ca9a5bb7a260cd8a174d6322ece", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.1", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "317346c14febaba9ca40fd97b5b5919f7751fb85d399cc8e7e8872049f37e0af"},
|
||||
"excoveralls": {:hex, :excoveralls, "0.18.0", "b92497e69465dc51bc37a6422226ee690ab437e4c06877e836f1c18daeb35da9", [:mix], [{:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "1109bb911f3cb583401760be49c02cbbd16aed66ea9509fc5479335d284da60b"},
|
||||
"expo": {:hex, :expo, "0.4.1", "1c61d18a5df197dfda38861673d392e642649a9cef7694d2f97a587b2cfb319b", [:mix], [], "hexpm", "2ff7ba7a798c8c543c12550fa0e2cbc81b95d4974c65855d8d15ba7b37a1ce47"},
|
||||
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
|
||||
"floki": {:hex, :floki, "0.35.2", "87f8c75ed8654b9635b311774308b2760b47e9a579dabf2e4d5f1e1d42c39e0b", [:mix], [], "hexpm", "6b05289a8e9eac475f644f09c2e4ba7e19201fd002b89c28c1293e7bd16773d9"},
|
||||
"gettext": {:hex, :gettext, "0.23.1", "821e619a240e6000db2fc16a574ef68b3bd7fe0167ccc264a81563cc93e67a31", [:mix], [{:expo, "~> 0.4.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "19d744a36b809d810d610b57c27b934425859d158ebd56561bc41f7eeb8795db"},
|
||||
"expo": {:hex, :expo, "0.5.2", "beba786aab8e3c5431813d7a44b828e7b922bfa431d6bfbada0904535342efe2", [:mix], [], "hexpm", "8c9bfa06ca017c9cb4020fabe980bc7fdb1aaec059fd004c2ab3bff03b1c599c"},
|
||||
"file_system": {:hex, :file_system, "1.0.0", "b689cc7dcee665f774de94b5a832e578bd7963c8e637ef940cd44327db7de2cd", [:mix], [], "hexpm", "6752092d66aec5a10e662aefeed8ddb9531d79db0bc145bb8c40325ca1d8536d"},
|
||||
"floki": {:hex, :floki, "0.36.1", "712b7f2ba19a4d5a47dfe3e74d81876c95bbcbee44fe551f0af3d2a388abb3da", [:mix], [], "hexpm", "21ba57abb8204bcc70c439b423fc0dd9f0286de67dc82773a14b0200ada0995f"},
|
||||
"gettext": {:hex, :gettext, "0.24.0", "6f4d90ac5f3111673cbefc4ebee96fe5f37a114861ab8c7b7d5b30a1108ce6d8", [:mix], [{:expo, "~> 0.5.1", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "bdf75cdfcbe9e4622dd18e034b227d77dd17f0f133853a1c73b97b3d6c770e8b"},
|
||||
"git_cli": {:hex, :git_cli, "0.3.0", "a5422f9b95c99483385b976f5d43f7e8233283a47cda13533d7c16131cb14df5", [:mix], [], "hexpm", "78cb952f4c86a41f4d3511f1d3ecb28edb268e3a7df278de2faa1bd4672eaf9b"},
|
||||
"git_ops": {:hex, :git_ops, "2.6.0", "e0791ee1cf5db03f2c61b7ebd70e2e95cba2bb9b9793011f26609f22c0900087", [:mix], [{:git_cli, "~> 0.2", [hex: :git_cli, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "b98fca849b18aaf490f4ac7d1dd8c6c469b0cc3e6632562d366cab095e666ffe"},
|
||||
"jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"},
|
||||
"libgraph": {:hex, :libgraph, "0.16.0", "3936f3eca6ef826e08880230f806bfea13193e49bf153f93edcf0239d4fd1d07", [:mix], [], "hexpm", "41ca92240e8a4138c30a7e06466acc709b0cbb795c643e9e17174a178982d6bf"},
|
||||
"makeup": {:hex, :makeup, "1.1.1", "fa0bc768698053b2b3869fa8a62616501ff9d11a562f3ce39580d60860c3a55e", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "5dc62fbdd0de44de194898b6710692490be74baa02d9d108bc29f007783b0b48"},
|
||||
"makeup_elixir": {:hex, :makeup_elixir, "0.16.1", "cc9e3ca312f1cfeccc572b37a09980287e243648108384b97ff2b76e505c3555", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "e127a341ad1b209bd80f7bd1620a15693a9908ed780c3b763bccf7d200c767c6"},
|
||||
"makeup_erlang": {:hex, :makeup_erlang, "0.1.3", "d684f4bac8690e70b06eb52dad65d26de2eefa44cd19d64a8095e1417df7c8fd", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "b78dc853d2e670ff6390b605d807263bf606da3c82be37f9d7f68635bd886fc9"},
|
||||
"makeup_elixir": {:hex, :makeup_elixir, "0.16.2", "627e84b8e8bf22e60a2579dad15067c755531fea049ae26ef1020cad58fe9578", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "41193978704763f6bbe6cc2758b84909e62984c7752b3784bd3c218bb341706b"},
|
||||
"makeup_erlang": {:hex, :makeup_erlang, "0.1.5", "e0ff5a7c708dda34311f7522a8758e23bfcd7d8d8068dc312b5eb41c6fd76eba", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "94d2e986428585a21516d7d7149781480013c56e30c6a233534bedf38867a59a"},
|
||||
"mime": {:hex, :mime, "2.0.5", "dc34c8efd439abe6ae0343edbb8556f4d63f178594894720607772a041b04b02", [:mix], [], "hexpm", "da0d64a365c45bc9935cc5c8a7fc5e49a0e0f9932a761c55d6c52b142780a05c"},
|
||||
"nimble_options": {:hex, :nimble_options, "1.1.0", "3b31a57ede9cb1502071fade751ab0c7b8dbe75a9a4c2b5bbb0943a690b63172", [:mix], [], "hexpm", "8bbbb3941af3ca9acc7835f5655ea062111c9c27bcac53e004460dfd19008a99"},
|
||||
"nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"},
|
||||
"phoenix": {:hex, :phoenix, "1.7.11", "1d88fc6b05ab0c735b250932c4e6e33bfa1c186f76dcf623d8dd52f07d6379c7", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "b1ec57f2e40316b306708fe59b92a16b9f6f4bf50ccfa41aa8c7feb79e0ec02a"},
|
||||
"phoenix_html": {:hex, :phoenix_html, "4.1.1", "4c064fd3873d12ebb1388425a8f2a19348cef56e7289e1998e2d2fa758aa982e", [:mix], [], "hexpm", "f2f2df5a72bc9a2f510b21497fd7d2b86d932ec0598f0210fed4114adc546c6f"},
|
||||
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.4.1", "2aff698f5e47369decde4357ba91fc9c37c6487a512b41732818f2204a8ef1d3", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "9bffb834e7ddf08467fe54ae58b5785507aaba6255568ae22b4d46e2bb3615ab"},
|
||||
"phoenix_live_view": {:hex, :phoenix_live_view, "0.20.12", "3f4b5849b8018023c01e41a7da2e6c986222cc3f0282858f8af11221638645cb", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ae3a143cc33325f3a4c192b7da1726e6665e154c50e1461af4cd7d561ccfd9ab"},
|
||||
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.5.3", "f2161c207fda0e4fb55165f650f7f8db23f02b29e3bff00ff7ef161d6ac1f09d", [:mix], [{:file_system, "~> 0.3 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "b4ec9cd73cb01ff1bd1cac92e045d13e7030330b74164297d1aee3907b54803c"},
|
||||
"phoenix_live_view": {:hex, :phoenix_live_view, "0.20.14", "70fa101aa0539e81bed4238777498f6215e9dda3461bdaa067cad6908110c364", [:mix], [{:floki, "~> 0.36", [hex: :floki, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "82f6d006c5264f979ed5eb75593d808bbe39020f20df2e78426f4f2d570e2402"},
|
||||
"phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.3", "3168d78ba41835aecad272d5e8cd51aa87a7ac9eb836eabc42f6e57538e3731d", [:mix], [], "hexpm", "bba06bc1dcfd8cb086759f0edc94a8ba2bc8896d5331a1e2c2902bf8e36ee502"},
|
||||
"phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"},
|
||||
"phoenix_view": {:hex, :phoenix_view, "2.0.3", "4d32c4817fce933693741deeb99ef1392619f942633dde834a5163124813aad3", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}], "hexpm", "cd34049af41be2c627df99cd4eaa71fc52a328c0c3d8e7d4aa28f880c30e7f64"},
|
||||
|
@ -50,15 +50,17 @@
|
|||
"plug_crypto": {:hex, :plug_crypto, "2.0.0", "77515cc10af06645abbfb5e6ad7a3e9714f805ae118fa1a70205f80d2d70fe73", [:mix], [], "hexpm", "53695bae57cc4e54566d993eb01074e4d894b65a3766f1c43e2c61a1b0f45ea9"},
|
||||
"postgrex": {:hex, :postgrex, "0.17.5", "0483d054938a8dc069b21bdd636bf56c487404c241ce6c319c1f43588246b281", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "50b8b11afbb2c4095a3ba675b4f055c416d0f3d7de6633a595fc131a828a67eb"},
|
||||
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
|
||||
"reactor": {:hex, :reactor, "0.7.0", "fb76d23d95829b28ac9b9d654620c43c890c6a32ea26ac13086c48540b34e8c5", [:mix], [{:libgraph, "~> 0.16", [hex: :libgraph, repo: "hexpm", optional: false]}, {:spark, "~> 1.0", [hex: :spark, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.2", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4310da820d753aafd7dc4ee8cc687b84565dd6d9536e38806ee211da792178fd"},
|
||||
"reactor": {:hex, :reactor, "0.8.1", "1aec71d16083901277727c8162f6dd0f07e80f5ca98911b6ef4f2c95e6e62758", [:mix], [{:libgraph, "~> 0.16", [hex: :libgraph, repo: "hexpm", optional: false]}, {:spark, "~> 2.0", [hex: :spark, repo: "hexpm", optional: false]}, {:splode, "~> 0.2", [hex: :splode, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.2", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ae3936d97a3e4a316744f70c77b85345b08b70da334024c26e6b5eb8ede1246b"},
|
||||
"simple_sat": {:hex, :simple_sat, "0.1.1", "68a5ebe6f6d5956bd806e4881c495692c14580a2f1a4420488985abd0fba2119", [:mix], [], "hexpm", "63571218f92ff029838df7645eb8f0c38df8ed60d2d14578412a8d142a94471e"},
|
||||
"sobelow": {:hex, :sobelow, "0.13.0", "218afe9075904793f5c64b8837cc356e493d88fddde126a463839351870b8d1e", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "cd6e9026b85fc35d7529da14f95e85a078d9dd1907a9097b3ba6ac7ebbe34a0d"},
|
||||
"sourceror": {:hex, :sourceror, "1.0.2", "c5e86fdc14881f797749d1fe5df017ca66727a8146e7ee3e736605a3df78f3e6", [:mix], [], "hexpm", "832335e87d0913658f129d58b2a7dc0490ddd4487b02de6d85bca0169ec2bd79"},
|
||||
"spark": {:hex, :spark, "1.1.55", "d20c3f899b23d841add29edc912ffab4463d3bb801bc73448738631389291d2e", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.5 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.0", [hex: :sourceror, repo: "hexpm", optional: false]}], "hexpm", "bbc15a4223d8e610c81ceca825d5d0bae3738d1c4ac4dbb1061749966776c3f1"},
|
||||
"spark": {:hex, :spark, "2.1.10", "f32cf6a0231f7a8a128889ee82682d53743c05b9c5b26392fefc0513b9be06d7", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.0", [hex: :sourceror, repo: "hexpm", optional: false]}], "hexpm", "86a88091a754ea2a4ed6dbc919e57e60828112b3552de14adb83ee20064813a2"},
|
||||
"splode": {:hex, :splode, "0.2.1", "020079ec06c9e00f8b6586852e781b5e07aee6ba588f3f45dd993831c87b0511", [:mix], [], "hexpm", "d232a933666061fe1f659d9906042fa94b9b393bb1129a4fde6fa680033b2611"},
|
||||
"stream_data": {:hex, :stream_data, "0.6.0", "e87a9a79d7ec23d10ff83eb025141ef4915eeb09d4491f79e52f2562b73e5f47", [:mix], [], "hexpm", "b92b5031b650ca480ced047578f1d57ea6dd563f5b57464ad274718c9c29501c"},
|
||||
"tails": {:hex, :tails, "0.1.7", "d77a89c2faea02237d78ea81824c1362dbc3cfa4e2a203be7808617ae47bb5eb", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "d5ae73c55d181ab1353f2c49aea2ef540edfa6ec6be65a89e8a392ba15a94b21"},
|
||||
"tails": {:hex, :tails, "0.1.10", "2edae202ad8b73bc9cb62fac20dec280549d7d7817e50027698c2f1de21bbc34", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "20ab7dd4d75e946daa67b83c1a392d9d87f7b1d3620ccbfe0ba2fb1debabd457"},
|
||||
"tailwind": {:hex, :tailwind, "0.2.2", "9e27288b568ede1d88517e8c61259bc214a12d7eed271e102db4c93fcca9b2cd", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "ccfb5025179ea307f7f899d1bb3905cd0ac9f687ed77feebc8f67bdca78565c4"},
|
||||
"telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"},
|
||||
"typable": {:hex, :typable, "0.3.0", "0431e121d124cd26f312123e313d2689b9a5322b15add65d424c07779eaa3ca1", [:mix], [], "hexpm", "880a0797752da1a4c508ac48f94711e04c86156f498065a83d160eef945858f8"},
|
||||
"websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"},
|
||||
"websock_adapter": {:hex, :websock_adapter, "0.5.5", "9dfeee8269b27e958a65b3e235b7e447769f66b5b5925385f5a569269164a210", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "4b977ba4a01918acbf77045ff88de7f6972c2a009213c515a445c48f224ffce9"},
|
||||
"websock_adapter": {:hex, :websock_adapter, "0.5.6", "0437fe56e093fd4ac422de33bf8fc89f7bc1416a3f2d732d8b2c8fd54792fe60", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "e04378d26b0af627817ae84c92083b7e97aca3121196679b73c73b99d0d133ea"},
|
||||
}
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
defmodule AshAdmin.Test.Api do
|
||||
@moduledoc false
|
||||
use Ash.Api,
|
||||
extensions: [AshAdmin.Api]
|
||||
|
||||
admin do
|
||||
show? true
|
||||
end
|
||||
|
||||
resources do
|
||||
registry(AshAdmin.Test.Registry)
|
||||
end
|
||||
end
|
13
test/support/domain.ex
Normal file
13
test/support/domain.ex
Normal file
|
@ -0,0 +1,13 @@
|
|||
defmodule AshAdmin.Test.Domain do
|
||||
@moduledoc false
|
||||
use Ash.Domain,
|
||||
extensions: [AshAdmin.Domain]
|
||||
|
||||
admin do
|
||||
show? true
|
||||
end
|
||||
|
||||
resources do
|
||||
resource(AshAdmin.Test.Post)
|
||||
end
|
||||
end
|
|
@ -1,8 +0,0 @@
|
|||
defmodule AshAdmin.Test.Registry do
|
||||
@moduledoc false
|
||||
use Ash.Registry
|
||||
|
||||
entries do
|
||||
entry(AshAdmin.Test.Post)
|
||||
end
|
||||
end
|
|
@ -1,6 +1,7 @@
|
|||
defmodule AshAdmin.Test.Post do
|
||||
@moduledoc false
|
||||
use Ash.Resource,
|
||||
domain: Demo.Tickets.Domain,
|
||||
data_layer: Ash.DataLayer.Ets
|
||||
|
||||
attributes do
|
||||
|
@ -8,6 +9,7 @@ defmodule AshAdmin.Test.Post do
|
|||
|
||||
attribute :body, :string do
|
||||
allow_nil?(false)
|
||||
public? true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue