fix: use static routes

This commit is contained in:
Zach Daniel 2021-03-22 17:44:34 -04:00
parent 7dec87b43e
commit aa464fea36
15 changed files with 240 additions and 347 deletions

View file

@ -23,9 +23,18 @@ defmodule AshAdmin.Api do
"""
def name(api) do
Ash.Dsl.Extension.get_opt(api, [:admin], :name, nil, true) ||
api
|> Module.split()
|> Enum.at(-2)
Ash.Dsl.Extension.get_opt(api, [:admin], :name, nil, true) || default_name(api)
end
defp default_name(api) do
split = api |> Module.split()
case List.last(split) do
"Api" ->
Enum.at(split, -2)
last ->
last
end
end
end

View file

@ -17,6 +17,7 @@ defmodule AshAdmin.Components.Resource.DataTable do
prop(params, :any)
prop(table, :any, required: true)
prop(tables, :any, required: true)
prop(prefix, :any, required: true)
data(initialized, :boolean, default: false)
data(data, :any)
@ -202,6 +203,7 @@ defmodule AshAdmin.Components.Resource.DataTable do
api={{ @api }}
set_actor={{ @set_actor }}
attributes={{ AshAdmin.Resource.table_columns(@resource) }}
prefix={{ @prefix }}
/>
{{ render_pagination_links(assigns, :bottom) }}
</div>

View file

@ -32,6 +32,7 @@ defmodule AshAdmin.Components.Resource.Form do
prop(action, :any, required: true)
prop(table, :any, required: true)
prop(tables, :any, required: true)
prop(prefix, :any, required: true)
def update(assigns, socket) do
{:ok,
@ -70,8 +71,13 @@ defmodule AshAdmin.Components.Resource.Form do
<div class="shadow-lg overflow-hidden sm:rounded-md bg-white">
<div :if={{ @changeset.action_failed? }} class="ml-4 mt-4 text-red-500">
<ul>
<li :for={{ {field, message} <- AshPhoenix.errors_for(@changeset, as: :simple) }}>
{{ to_name(field) }}: {{ message }}
<li :for={{ {field, message} <- errors_for(@changeset) }}>
<span :if={{field}}>
{{ to_name(field) }}:
</span>
<span>
{{message}}
</span>
</li>
</ul>
</div>
@ -123,6 +129,18 @@ defmodule AshAdmin.Components.Resource.Form do
"""
end
defp errors_for(changeset) do
changeset
|> AshPhoenix.transform_errors(fn
_, %{class: :forbidden} ->
{nil, "Forbidden", []}
_, other ->
other
end)
|> AshPhoenix.errors_for(as: :simple)
end
defp save_button_text(:update), do: "Save"
defp save_button_text(type), do: type |> to_string() |> String.capitalize()
@ -560,19 +578,16 @@ defmodule AshAdmin.Components.Resource.Form do
defp text_input_type(_), do: "text"
defp redirect_to(socket, record) do
show_action = AshAdmin.Resource.show_action(socket.assigns.resource)
if show_action do
if AshAdmin.Resource.show_action(socket.assigns.resource) do
{:noreply,
socket
|> redirect(
to:
ash_show_path(
socket,
socket.assigns.prefix,
socket.assigns.api,
socket.assigns.resource,
record,
show_action,
socket.assigns.table
)
)}
@ -580,7 +595,10 @@ defmodule AshAdmin.Components.Resource.Form do
case Ash.Resource.Info.primary_action(socket.assigns.resource, :update) do
nil ->
{:noreply,
redirect(socket, to: ash_admin_path(socket.assigns.api, socket.assigns.resource))}
redirect(socket,
to:
ash_admin_path(socket.assigns.prefix, socket.assigns.api, socket.assigns.resource)
)}
update ->
{:noreply,
@ -588,7 +606,7 @@ defmodule AshAdmin.Components.Resource.Form do
|> redirect(
to:
ash_update_path(
socket,
socket.assigns.prefix,
socket.assigns.api,
socket.assigns.resource,
record,
@ -607,7 +625,7 @@ defmodule AshAdmin.Components.Resource.Form do
push_redirect(socket,
to:
ash_create_path(
socket,
socket.assigns.prefix,
socket.assigns.api,
socket.assigns.resource,
socket.assigns.action.name,
@ -620,7 +638,7 @@ defmodule AshAdmin.Components.Resource.Form do
push_redirect(socket,
to:
ash_update_path(
socket,
socket.assigns.prefix,
socket.assigns.api,
socket.assigns.resource,
socket.assigns.record,
@ -634,7 +652,7 @@ defmodule AshAdmin.Components.Resource.Form do
push_redirect(socket,
to:
ash_destroy_path(
socket,
socket.assigns.prefix,
socket.assigns.api,
socket.assigns.resource,
socket.assigns.record,
@ -664,7 +682,7 @@ defmodule AshAdmin.Components.Resource.Form do
push_redirect(socket,
to:
ash_create_path(
socket,
socket.assigns.prefix,
socket.assigns.api,
socket.assigns.resource,
action.name,
@ -677,7 +695,21 @@ defmodule AshAdmin.Components.Resource.Form do
push_redirect(socket,
to:
ash_update_path(
socket,
socket.assigns.prefix,
socket.assigns.api,
socket.assigns.resource,
socket.assigns.record,
action.name,
socket.assigns.table
)
)}
:destroy ->
{:noreply,
push_redirect(socket,
to:
ash_destroy_path(
socket.assigns.prefix,
socket.assigns.api,
socket.assigns.resource,
socket.assigns.record,
@ -775,7 +807,7 @@ defmodule AshAdmin.Components.Resource.Form do
{:ok, created} ->
redirect_to(socket, created)
{:error, %{changeset: changeset}} ->
{:error, %{changeset: changeset} = error} ->
{:noreply, assign(socket, :changeset, changeset)}
end
@ -813,7 +845,14 @@ defmodule AshAdmin.Components.Resource.Form do
:ok ->
{:noreply,
socket
|> redirect(to: ash_admin_path(socket, socket.assigns.api, socket.assigns.resource))}
|> redirect(
to:
ash_admin_path(
socket.assigns.prefix,
socket.assigns.api,
socket.assigns.resource
)
)}
{:error, %{changeset: changeset}} ->
{:noreply, assign(socket, :changeset, changeset)}

View file

@ -10,6 +10,7 @@ defmodule AshAdmin.Components.Resource.Nav do
prop(tab, :string, required: true)
prop(action, :any)
prop(table, :any, default: nil)
prop(prefix, :any, default: nil)
def render(assigns) do
~H"""
@ -19,7 +20,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">
<LiveRedirect to={{ ash_admin_path(@socket, @api, @resource) }}>
<LiveRedirect to={{ ash_admin_path(@prefix, @api, @resource) }}>
{{ AshAdmin.Resource.name(@resource) }}
</LiveRedirect>
</h3>
@ -29,7 +30,7 @@ defmodule AshAdmin.Components.Resource.Nav do
<div :if={{ has_create_action?(@resource) }} class="relative">
<LiveRedirect
to={{ash_create_path(
@socket,
@prefix,
@api,
@resource,
Ash.Resource.Info.primary_action(@resource, :create).name,
@ -45,7 +46,7 @@ defmodule AshAdmin.Components.Resource.Nav do
name="Read"
id={{ "#{@resource}_data_dropdown" }}
active={{ @tab == "data" }}
groups={{ data_groups(@socket, @api, @resource, @action, @table) }}
groups={{ data_groups(@prefix, @api, @resource, @action, @table) }}
/>
</div>
</div>
@ -56,7 +57,7 @@ defmodule AshAdmin.Components.Resource.Nav do
"""
end
defp data_groups(socket, api, resource, current_action, table) do
defp data_groups(prefix, api, resource, current_action, table) do
read_actions = AshAdmin.Resource.read_actions(resource)
[
@ -67,7 +68,7 @@ defmodule AshAdmin.Components.Resource.Nav do
|> Enum.map(fn action ->
%{
text: action_name(action),
to: ash_action_path(socket, api, resource, :read, action.name, table),
to: ash_action_path(prefix, api, resource, :read, action.name, table),
active: current_action == action
}
end)

View file

@ -6,6 +6,7 @@ defmodule AshAdmin.Components.Resource.RelationshipTable do
prop(resource, :any, required: true)
prop(api, :any, required: true)
prop(prefix, :any, required: true)
def render(assigns) do
~H"""
@ -33,7 +34,7 @@ defmodule AshAdmin.Components.Resource.RelationshipTable do
<td class="text-center">
{{ relationship.type }}</td>
<td class="text-center">
<LiveRedirect to={{ ash_admin_path(@socket, @api, relationship.destination) }}>
<LiveRedirect to={{ ash_admin_path(@prefix, @api, relationship.destination) }}>
{{ AshAdmin.Resource.name(relationship.destination) }}
</LiveRedirect>
</td>

View file

@ -21,6 +21,7 @@ defmodule AshAdmin.Components.Resource do
prop(record, :any, default: nil)
prop(table, :any, default: nil)
prop(tables, :any, default: nil)
prop(prefix, :any, default: nil)
data(filter_open, :boolean, default: false)
slot(default)
@ -34,6 +35,7 @@ defmodule AshAdmin.Components.Resource do
tab={{ @tab }}
action={{ @action }}
table={{ @table }}
prefix={{ @prefix }}
/>
<div class="mx-24 relative grid grid-cols-1 justify-items-center">
</div>
@ -54,6 +56,7 @@ defmodule AshAdmin.Components.Resource do
tenant={{ @tenant }}
table={{ @table }}
tables={{ @tables }}
prefix={{ @prefix }}
/>
</div>
<div :if={{ @record && match?({:ok, record} when not is_nil(record), @record) && @tab == "destroy" }}>
@ -72,6 +75,7 @@ defmodule AshAdmin.Components.Resource do
tenant={{ @tenant }}
table={{ @table }}
tables={{ @tables }}
prefix={{ @prefix }}
/>
</div>
<Show
@ -85,8 +89,9 @@ defmodule AshAdmin.Components.Resource do
tenant={{ @tenant }}
set_actor={{ @set_actor }}
table={{ @table }}
prefix={{ @prefix }}
/>
<Info :if={{ @tab == "info" }} resource={{ @resource }} api={{ @api }} />
<Info :if={{ @tab == "info" }} resource={{ @resource }} api={{ @api }} prefix={{ @prefix }} />
<Form
:if={{ @tab == "create" }}
type={{ :create }}
@ -100,6 +105,7 @@ defmodule AshAdmin.Components.Resource do
tenant={{ @tenant }}
table={{ @table }}
tables={{ @tables }}
prefix={{ @prefix }}
/>
<DataTable
:if={{ @tab == "data" }}
@ -114,6 +120,7 @@ defmodule AshAdmin.Components.Resource do
authorizing={{ @authorizing }}
table={{ @table }}
tables={{ @tables }}
prefix={{ @prefix }}
/>
</div>
"""

View file

@ -6,12 +6,13 @@ defmodule AshAdmin.Components.Resource.Info do
prop(resource, :any, required: true)
prop(api, :any, required: true)
prop(prefix, :any, required: true)
def render(assigns) do
~H"""
<div class="relative mx-12">
<AttributeTable resource={{ @resource }} />
<RelationshipTable api={{ @api }} resource={{ @resource }} />
<RelationshipTable api={{ @api }} resource={{ @resource }} prefix={{ @prefix }} />
</div>
"""
end

View file

@ -15,6 +15,7 @@ defmodule AshAdmin.Components.Resource.Show do
prop(tenant, :any)
prop(set_actor, :event, required: true)
prop(table, :any, required: true)
prop(prefix, :any, required: true)
data(load_errors, :map, default: %{})
@ -55,7 +56,7 @@ defmodule AshAdmin.Components.Resource.Show do
<div :if={{ buttons? }} class="px-4 py-3 text-right sm:px-6">
<LiveRedirect
to={{ash_destroy_path(
@socket,
@prefix,
@api,
@resource,
@record,
@ -70,7 +71,7 @@ defmodule AshAdmin.Components.Resource.Show do
<LiveRedirect
to={{ash_update_path(
@socket,
@prefix,
@api,
@resource,
@record,
@ -144,11 +145,10 @@ defmodule AshAdmin.Components.Resource.Show do
<LiveRedirect
:if={{ AshAdmin.Resource.show_action(destination) }}
to={{ash_show_path(
@socket,
@prefix,
@api,
destination,
record,
AshAdmin.Resource.show_action(destination),
context[:data_layer][:table]
)}}
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"
@ -178,6 +178,7 @@ defmodule AshAdmin.Components.Resource.Show do
api={{ @api }}
set_actor={{ @set_actor }}
table={{ context[:data_layer][:table] }}
prefix={{ @prefix }}
/>
</div>
"""
@ -187,7 +188,7 @@ defmodule AshAdmin.Components.Resource.Show do
~H"""
{{ {attributes, flags, bottom_attributes} =
AshAdmin.Components.Resource.Form.attributes(resource, :show)
nil }}
<div class="grid grid-cols-6 gap-6">
<div

View file

@ -12,6 +12,7 @@ defmodule AshAdmin.Components.Resource.Table do
prop(api, :any, required: true)
prop(set_actor, :event, required: true)
prop(table, :any, required: true)
prop(prefix, :any, required: true)
def render(assigns) do
~H"""
@ -28,14 +29,14 @@ 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) }}>
<LiveRedirect to={{ ash_show_path(@socket, @api, @resource, record, AshAdmin.Resource.show_action(@resource), @table) }}>
<LiveRedirect to={{ ash_show_path(@prefix, @api, @resource, record, @table) }}>
{{ {:safe, Heroicons.Solid.information_circle(class: "h-5 w-5 text-gray-500")} }}
</LiveRedirect>
</div>
<div :if={{ Ash.Resource.Info.primary_action(@resource, :update) }}>
<LiveRedirect to={{ash_update_path(
@socket,
@prefix,
@api,
@resource,
record,
@ -48,7 +49,7 @@ defmodule AshAdmin.Components.Resource.Table do
<div :if={{ Ash.Resource.Info.primary_action(@resource, :destroy) }}>
<LiveRedirect to={{ash_destroy_path(
@socket,
@prefix,
@api,
@resource,
record,

View file

@ -21,6 +21,7 @@ defmodule AshAdmin.Components.TopNav do
prop(actor_paused, :boolean, required: true)
prop(actor, :any, required: true)
prop(actor_api, :any, required: true)
prop(prefix, :any, required: true)
def render(assigns) do
~H"""
@ -30,7 +31,7 @@ defmodule AshAdmin.Components.TopNav do
<div class="flex items-center w-full">
<div class="flex-shrink-0">
<h3 class="text-white text-lg">
<LiveRedirect to={{ ash_admin_path(@socket) }}>
<LiveRedirect to={{ ash_admin_path(@prefix) }}>
Admin
</LiveRedirect>
</h3>
@ -44,7 +45,7 @@ defmodule AshAdmin.Components.TopNav do
class="mr-1"
id={{ AshAdmin.Api.name(api) <> "_api_nav" }}
name={{ AshAdmin.Api.name(api) }}
groups={{ dropdown_groups(@socket, @resource, api) }}
groups={{ dropdown_groups(@prefix, @resource, api) }}
/>
</div>
<div class="ml-10 flex items-center">
@ -59,6 +60,7 @@ defmodule AshAdmin.Components.TopNav do
clear_actor={{ @clear_actor }}
actor_api={{ @actor_api }}
api={{ @api }}
prefix={{ @prefix }}
/>
<TenantForm
:if={{ show_tenant_form?(@apis) }}
@ -112,6 +114,7 @@ defmodule AshAdmin.Components.TopNav do
clear_actor={{ @clear_actor }}
actor_api={{ @actor_api }}
api={{ @api }}
prefix={{ @prefix }}
/>
</div>
<div class="block px-4 py-2 text-sm">
@ -127,7 +130,7 @@ defmodule AshAdmin.Components.TopNav do
:for={{ api <- @apis }}
id={{ AshAdmin.Api.name(api) <> "_api_nav_drawer" }}
name={{ AshAdmin.Api.name(api) }}
groups={{ dropdown_groups(@socket, @resource, api) }}
groups={{ dropdown_groups(@prefix, @resource, api) }}
/>
</div>
</div>
@ -135,12 +138,12 @@ defmodule AshAdmin.Components.TopNav do
"""
end
defp dropdown_groups(socket, current_resource, api) do
defp dropdown_groups(prefix, current_resource, api) do
[
for resource <- Ash.Api.resources(api) do
%{
text: AshAdmin.Resource.name(resource),
to: ash_admin_path(socket, api, resource),
to: ash_admin_path(prefix, api, resource),
active: resource == current_resource
}
end

View file

@ -15,6 +15,7 @@ defmodule AshAdmin.Components.TopNav.ActorSelect do
prop(clear_actor, :event, required: true)
prop(api, :any, required: true)
prop(actor_api, :any, required: true)
prop(prefix, :any, required: true)
def render(assigns) do
~H"""
@ -74,11 +75,10 @@ defmodule AshAdmin.Components.TopNav.ActorSelect do
<LiveRedirect
class="hover:text-blue-400 hover:underline"
to={{ash_show_path(
@socket,
@prefix,
@actor_api,
@actor.__struct__,
@actor,
AshAdmin.Resource.show_action(@actor.__struct__),
nil
)}}
>
@ -108,7 +108,7 @@ defmodule AshAdmin.Components.TopNav.ActorSelect do
defp render_actor_link(assigns, [{api, resource}]) do
~H"""
<LiveRedirect to={{ash_action_path(
@socket,
@prefix,
api,
resource,
:read,
@ -125,7 +125,7 @@ defmodule AshAdmin.Components.TopNav.ActorSelect do
<div aria-labelledby="actor-banner">
<LiveRedirect
to={{ash_action_path(
@socket,
@prefix,
api,
resource,
:read,

View file

@ -47,10 +47,6 @@ defmodule AshAdmin.Helpers do
Ash.Changeset.set_context(changeset, %{data_layer: %{table: table}})
end
def ash_admin_path(socket) do
apply(socket.router.__helpers__(), :ash_admin_path, [socket, :page])
end
def self_path(url_path, socket_params, new_params) do
url_path <>
"?" <>
@ -88,238 +84,135 @@ defmodule AshAdmin.Helpers do
end
end
@doc """
TODO
"""
def ash_admin_path(socket, api) do
apply(
socket.router.__helpers__(),
String.to_existing_atom(String.downcase(AshAdmin.Api.name(api) <> "_path")),
[socket, :api_page]
defp prefix(nil, path), do: path
defp prefix(prefix, path), do: prefix <> path
def ash_admin_path(prefix) do
prefix(prefix, "/")
end
def ash_admin_path(prefix, api) do
prefix(prefix, "/#{AshAdmin.Api.name(api)}")
end
def ash_admin_path(prefix, api, resource) do
prefix(
prefix,
"/#{AshAdmin.Api.name(api)}/#{AshAdmin.Resource.name(resource)}"
)
end
def ash_admin_path(socket, api, resource) do
route =
String.to_existing_atom(
String.downcase(AshAdmin.Api.name(api) <> AshAdmin.Resource.name(resource) <> "_path")
)
apply(
socket.router.__helpers__(),
route,
[socket, :resource_page]
def ash_create_path(prefix, api, resource) do
prefix(
prefix,
"/#{AshAdmin.Api.name(api)}/#{AshAdmin.Resource.name(resource)}/create"
)
end
def ash_create_path(socket, api, resource) do
route =
String.to_existing_atom(
String.downcase(
AshAdmin.Api.name(api) <> AshAdmin.Resource.name(resource) <> "create_path"
)
)
apply(
socket.router.__helpers__(),
route,
[socket, :resource_page]
def ash_create_path(prefix, api, resource, action_name, nil) do
prefix(
prefix,
"/#{AshAdmin.Api.name(api)}/#{AshAdmin.Resource.name(resource)}/create/#{action_name}"
)
end
def ash_create_path(socket, api, resource, action_name, nil) do
route =
String.to_existing_atom(
String.downcase(
AshAdmin.Api.name(api) <>
AshAdmin.Resource.name(resource) <> "create" <> to_string(action_name) <> "_path"
)
)
apply(
socket.router.__helpers__(),
route,
[socket, :resource_page]
def ash_create_path(prefix, api, resource, action_name, table) do
prefix(
prefix,
"/#{AshAdmin.Api.name(api)}/#{AshAdmin.Resource.name(resource)}/#{table}/create/#{
action_name
}"
)
end
def ash_create_path(socket, api, resource, action_name, table) do
route =
String.to_existing_atom(
String.downcase(
AshAdmin.Api.name(api) <>
AshAdmin.Resource.name(resource) <>
table <>
"create" <> to_string(action_name) <> "_path"
)
)
apply(
socket.router.__helpers__(),
route,
[socket, :resource_page]
def ash_update_path(prefix, api, resource, record) do
prefix(
prefix,
"/#{AshAdmin.Api.name(api)}/#{AshAdmin.Resource.name(resource)}/update/#{
encode_primary_key(record)
}"
)
end
def ash_update_path(socket, api, resource, record) do
route =
String.to_existing_atom(
String.downcase(
AshAdmin.Api.name(api) <> AshAdmin.Resource.name(resource) <> "update_path"
)
)
apply(
socket.router.__helpers__(),
route,
[socket, :resource_page, encode_primary_key(record)]
def ash_update_path(prefix, api, resource, record, action_name, nil) do
prefix(
prefix,
"/#{AshAdmin.Api.name(api)}/#{AshAdmin.Resource.name(resource)}/update/#{action_name}/#{
encode_primary_key(record)
}"
)
end
def ash_update_path(socket, api, resource, record, action_name, nil) do
route =
String.to_existing_atom(
String.downcase(
AshAdmin.Api.name(api) <>
AshAdmin.Resource.name(resource) <> "update" <> to_string(action_name) <> "_path"
)
)
apply(
socket.router.__helpers__(),
route,
[socket, :resource_page, encode_primary_key(record)]
def ash_update_path(prefix, api, resource, record, action_name, table) do
prefix(
prefix,
"/#{AshAdmin.Api.name(api)}/#{AshAdmin.Resource.name(resource)}/#{table}/update/#{
action_name
}/#{encode_primary_key(record)}"
)
end
def ash_update_path(socket, api, resource, record, action_name, table) do
route =
String.to_existing_atom(
String.downcase(
AshAdmin.Api.name(api) <>
AshAdmin.Resource.name(resource) <>
table <> "update" <> to_string(action_name) <> "_path"
)
)
apply(
socket.router.__helpers__(),
route,
[socket, :resource_page, encode_primary_key(record)]
def ash_destroy_path(prefix, api, resource, record) do
prefix(
prefix,
"/#{AshAdmin.Api.name(api)}/#{AshAdmin.Resource.name(resource)}/destroy/#{
encode_primary_key(record)
}"
)
end
def ash_destroy_path(socket, api, resource, record) do
route =
String.to_existing_atom(
String.downcase(
AshAdmin.Api.name(api) <> AshAdmin.Resource.name(resource) <> "destroy_path"
)
)
apply(
socket.router.__helpers__(),
route,
[socket, :resource_page, encode_primary_key(record)]
def ash_destroy_path(prefix, api, resource, record, action_name, nil) do
prefix(
prefix,
"/#{AshAdmin.Api.name(api)}/#{AshAdmin.Resource.name(resource)}/destroy/#{action_name}/#{
encode_primary_key(record)
}"
)
end
def ash_destroy_path(socket, api, resource, record, action_name, nil) do
route =
String.to_existing_atom(
String.downcase(
AshAdmin.Api.name(api) <>
AshAdmin.Resource.name(resource) <> "destroy" <> to_string(action_name) <> "_path"
)
)
apply(
socket.router.__helpers__(),
route,
[socket, :resource_page, encode_primary_key(record)]
def ash_destroy_path(prefix, api, resource, record, action_name, table) do
prefix(
prefix,
"/#{AshAdmin.Api.name(api)}/#{AshAdmin.Resource.name(resource)}/#{table}/destroy/#{
action_name
}#{encode_primary_key(record)}"
)
end
def ash_destroy_path(socket, api, resource, record, action_name, table) do
route =
String.to_existing_atom(
String.downcase(
AshAdmin.Api.name(api) <>
AshAdmin.Resource.name(resource) <>
table <> "destroy" <> to_string(action_name) <> "_path"
)
)
apply(
socket.router.__helpers__(),
route,
[socket, :resource_page, encode_primary_key(record)]
def ash_action_path(prefix, api, resource, action_type, action_name, nil) do
prefix(
prefix,
"/#{AshAdmin.Api.name(api)}/#{AshAdmin.Resource.name(resource)}/#{action_type}/#{
action_name
}"
)
end
def ash_action_path(socket, api, resource, action_type, action_name, nil) do
route =
String.to_existing_atom(
String.downcase(
AshAdmin.Api.name(api) <>
AshAdmin.Resource.name(resource) <> "_#{action_type}" <> "_#{action_name}" <> "_path"
)
)
apply(
socket.router.__helpers__(),
route,
[socket, :resource_page]
)
end
def ash_action_path(socket, api, resource, action_type, action_name, table) do
route =
String.to_existing_atom(
String.downcase(
AshAdmin.Api.name(api) <>
AshAdmin.Resource.name(resource) <>
table <> "_#{action_type}" <> "_#{action_name}" <> "_path"
)
)
apply(
socket.router.__helpers__(),
route,
[socket, :resource_page]
def ash_action_path(prefix, api, resource, action_type, action_name, table) do
prefix(
prefix,
"/#{AshAdmin.Api.name(api)}/#{AshAdmin.Resource.name(resource)}/#{table}/#{action_type}/#{
action_name
}"
)
end
# sobelow_skip ["DOS.StringToAtom"]
def ash_show_path(socket, api, resource, record, action_name, nil) do
route =
String.to_existing_atom(
String.downcase(
AshAdmin.Api.name(api) <>
AshAdmin.Resource.name(resource) <> "_show" <> "_#{action_name}" <> "_path"
)
)
apply(
socket.router.__helpers__(),
route,
[socket, :show_page, encode_primary_key(record)]
def ash_show_path(prefix, api, resource, record, nil) do
prefix(
prefix,
"/#{AshAdmin.Api.name(api)}/#{AshAdmin.Resource.name(resource)}/show/#{
encode_primary_key(record)
}"
)
end
def ash_show_path(socket, api, resource, record, action_name, table) do
route =
String.to_existing_atom(
String.downcase(
AshAdmin.Api.name(api) <>
AshAdmin.Resource.name(resource) <> table <> "_show" <> "_#{action_name}" <> "_path"
)
)
apply(
socket.router.__helpers__(),
route,
[socket, :show_page, encode_primary_key(record)]
def ash_show_path(prefix, api, resource, record, table) do
prefix(
prefix,
"/#{AshAdmin.Api.name(api)}/#{AshAdmin.Resource.name(resource)}/#{table}/show/#{
encode_primary_key(record)
}"
)
end

View file

@ -19,6 +19,7 @@ defmodule AshAdmin.PageLive do
def mount(
_params,
%{
"prefix" => prefix,
"api" => api,
"apis" => apis,
"tab" => tab,
@ -28,6 +29,8 @@ defmodule AshAdmin.PageLive do
} = session,
socket
) do
socket = assign(socket, :prefix, prefix)
actor_paused =
if is_nil(session["actor_paused"]) do
true
@ -48,6 +51,7 @@ defmodule AshAdmin.PageLive do
{:ok,
socket
|> Surface.init()
|> assign(:prefix, prefix)
|> assign(:api, api)
|> assign(:apis, apis)
|> assign(:resource, resource)
@ -87,6 +91,7 @@ defmodule AshAdmin.PageLive do
toggle_authorizing="toggle_authorizing"
toggle_actor_paused="toggle_actor_paused"
clear_actor="clear_actor"
prefix={{ @prefix }}
/>
<Resource
:if={{ @resource }}
@ -105,6 +110,7 @@ defmodule AshAdmin.PageLive do
authorizing={{ @authorizing }}
table={{ @table }}
tables={{ @tables }}
prefix={{ @prefix }}
/>
"""
end

View file

@ -12,6 +12,8 @@ defmodule AshAdmin.Router do
```elixir
defmodule MyAppWeb.Router do
use Phoenix.Router
import AshAdmin.Router
admin_browser_pipeline :something
scope "/" do
@ -65,6 +67,13 @@ defmodule AshAdmin.Router do
scope path, alias: false, as: false do
import Phoenix.LiveView.Router, only: [live: 4]
prefix =
if opts[:prefix] do
opts[:prefix] <> path
else
path
end
apis = opts[:apis]
Enum.each(apis, &Code.ensure_compiled/1)
api = List.first(opts[:apis])
@ -78,7 +87,8 @@ defmodule AshAdmin.Router do
"/",
AshAdmin.PageLive,
:page,
AshAdmin.Router.__options__(opts, :ash_admin, %{
AshAdmin.Router.__options__(opts, %{
"prefix" => prefix,
"apis" => apis,
"api" => api,
"tab" => nil,
@ -89,17 +99,12 @@ defmodule AshAdmin.Router do
)
for api <- apis do
as =
api
|> AshAdmin.Api.name()
|> String.downcase()
|> String.to_atom()
live(
"/#{AshAdmin.Api.name(api)}",
AshAdmin.PageLive,
:api_page,
AshAdmin.Router.__options__(opts, as, %{
AshAdmin.Router.__options__(opts, %{
"prefix" => prefix,
"apis" => apis,
"api" => api,
"tab" => "info",
@ -112,19 +117,12 @@ defmodule AshAdmin.Router do
for resource <- Ash.Api.resources(api) do
for {table, alias_part, polymorphic_part} <-
AshAdmin.Router.polymorphic_parts(resource, apis) do
as =
api
|> AshAdmin.Api.name()
|> Kernel.<>(AshAdmin.Resource.name(resource))
|> Kernel.<>(alias_part)
|> String.downcase()
|> String.to_atom()
live(
"/#{AshAdmin.Api.name(api)}/#{AshAdmin.Resource.name(resource)}#{polymorphic_part}",
AshAdmin.PageLive,
:resource_page,
AshAdmin.Router.__options__(opts, as, %{
AshAdmin.Router.__options__(opts, %{
"prefix" => prefix,
"apis" => apis,
"api" => api,
"tab" => "info",
@ -136,22 +134,14 @@ defmodule AshAdmin.Router do
)
if Enum.any?(Ash.Resource.Info.actions(resource), &(&1.type == :create)) do
as =
api
|> AshAdmin.Api.name()
|> Kernel.<>(AshAdmin.Resource.name(resource))
|> Kernel.<>(alias_part)
|> Kernel.<>("create")
|> String.downcase()
|> String.to_atom()
live(
"/#{AshAdmin.Api.name(api)}/#{AshAdmin.Resource.name(resource)}#{
polymorphic_part
}/create",
AshAdmin.PageLive,
:resource_page,
AshAdmin.Router.__options__(opts, as, %{
AshAdmin.Router.__options__(opts, %{
"prefix" => prefix,
"apis" => apis,
"api" => api,
"resource" => resource,
@ -164,23 +154,14 @@ defmodule AshAdmin.Router do
end
for %{type: :create} = action <- Ash.Resource.Info.actions(resource) do
as =
api
|> AshAdmin.Api.name()
|> Kernel.<>(AshAdmin.Resource.name(resource))
|> Kernel.<>(alias_part)
|> Kernel.<>("create")
|> Kernel.<>(to_string(action.name))
|> String.downcase()
|> String.to_atom()
live(
"/#{AshAdmin.Api.name(api)}/#{AshAdmin.Resource.name(resource)}#{
polymorphic_part
}/create/#{action.name}",
AshAdmin.PageLive,
:resource_page,
AshAdmin.Router.__options__(opts, as, %{
AshAdmin.Router.__options__(opts, %{
"prefix" => prefix,
"apis" => apis,
"api" => api,
"resource" => resource,
@ -193,22 +174,14 @@ defmodule AshAdmin.Router do
end
if Enum.any?(Ash.Resource.Info.actions(resource), &(&1.type == :update)) do
as =
api
|> AshAdmin.Api.name()
|> Kernel.<>(AshAdmin.Resource.name(resource))
|> Kernel.<>(alias_part)
|> Kernel.<>("update")
|> String.downcase()
|> String.to_atom()
live(
"/#{AshAdmin.Api.name(api)}/#{AshAdmin.Resource.name(resource)}#{
polymorphic_part
}/update/:primary_key",
AshAdmin.PageLive,
:resource_page,
AshAdmin.Router.__options__(opts, as, %{
AshAdmin.Router.__options__(opts, %{
"prefix" => prefix,
"apis" => apis,
"api" => api,
"resource" => resource,
@ -220,23 +193,14 @@ defmodule AshAdmin.Router do
)
for %{type: :update} = action <- Ash.Resource.Info.actions(resource) do
as =
api
|> AshAdmin.Api.name()
|> Kernel.<>(AshAdmin.Resource.name(resource))
|> Kernel.<>(alias_part)
|> Kernel.<>("update")
|> Kernel.<>(to_string(action.name))
|> String.downcase()
|> String.to_atom()
live(
"/#{AshAdmin.Api.name(api)}/#{AshAdmin.Resource.name(resource)}#{
polymorphic_part
}/update/#{action.name}/:primary_key",
AshAdmin.PageLive,
:resource_page,
AshAdmin.Router.__options__(opts, as, %{
AshAdmin.Router.__options__(opts, %{
"prefix" => prefix,
"apis" => apis,
"api" => api,
"resource" => resource,
@ -250,22 +214,14 @@ defmodule AshAdmin.Router do
end
if Enum.any?(Ash.Resource.Info.actions(resource), &(&1.type == :destroy)) do
as =
api
|> AshAdmin.Api.name()
|> Kernel.<>(AshAdmin.Resource.name(resource))
|> Kernel.<>(alias_part)
|> Kernel.<>("destroy")
|> String.downcase()
|> String.to_atom()
live(
"/#{AshAdmin.Api.name(api)}/#{AshAdmin.Resource.name(resource)}#{
polymorphic_part
}/destroy/:primary_key",
AshAdmin.PageLive,
:resource_page,
AshAdmin.Router.__options__(opts, as, %{
AshAdmin.Router.__options__(opts, %{
"prefix" => prefix,
"apis" => apis,
"api" => api,
"resource" => resource,
@ -277,23 +233,14 @@ defmodule AshAdmin.Router do
)
for %{type: :destroy} = action <- Ash.Resource.Info.actions(resource) do
as =
api
|> AshAdmin.Api.name()
|> Kernel.<>(AshAdmin.Resource.name(resource))
|> Kernel.<>(alias_part)
|> Kernel.<>("destroy")
|> Kernel.<>(to_string(action.name))
|> String.downcase()
|> String.to_atom()
live(
"/#{AshAdmin.Api.name(api)}/#{AshAdmin.Resource.name(resource)}#{
polymorphic_part
}/destroy/#{action.name}/:primary_key",
AshAdmin.PageLive,
:resource_page,
AshAdmin.Router.__options__(opts, as, %{
AshAdmin.Router.__options__(opts, %{
"prefix" => prefix,
"apis" => apis,
"api" => api,
"resource" => resource,
@ -312,23 +259,14 @@ defmodule AshAdmin.Router do
action =
Ash.Resource.Info.action(resource, AshAdmin.Resource.show_action(resource))
as =
api
|> AshAdmin.Api.name()
|> Kernel.<>(AshAdmin.Resource.name(resource))
|> Kernel.<>(alias_part)
|> Kernel.<>("_show")
|> Kernel.<>("_#{action.name}")
|> String.downcase()
|> String.to_atom()
live(
"/#{AshAdmin.Api.name(api)}/#{AshAdmin.Resource.name(resource)}#{
polymorphic_part
}/show/:primary_key",
AshAdmin.PageLive,
:show_page,
AshAdmin.Router.__options__(opts, as, %{
AshAdmin.Router.__options__(opts, %{
"prefix" => prefix,
"apis" => apis,
"api" => api,
"resource" => resource,
@ -341,23 +279,14 @@ defmodule AshAdmin.Router do
end
for %{type: :read} = action <- Ash.Resource.Info.actions(resource) do
as =
api
|> AshAdmin.Api.name()
|> Kernel.<>(AshAdmin.Resource.name(resource))
|> Kernel.<>(alias_part)
|> Kernel.<>("_read")
|> Kernel.<>("_#{action.name}")
|> String.downcase()
|> String.to_atom()
live(
"/#{AshAdmin.Api.name(api)}/#{AshAdmin.Resource.name(resource)}#{
polymorphic_part
}/#{action.type}/#{action.name}",
AshAdmin.PageLive,
:resource_page,
AshAdmin.Router.__options__(opts, as, %{
AshAdmin.Router.__options__(opts, %{
"prefix" => prefix,
"apis" => apis,
"api" => api,
"resource" => resource,
@ -376,14 +305,13 @@ defmodule AshAdmin.Router do
end
@doc false
def __options__(options, as, session) do
def __options__(options, session) do
live_socket_path = Keyword.get(options, :live_socket_path, "/live")
[
session: {__MODULE__, :__session__, [session]},
private: %{live_socket_path: live_socket_path},
layout: {AshAdmin.LayoutView, :admin},
as: as
layout: {AshAdmin.LayoutView, :admin}
]
end

View file

@ -90,7 +90,8 @@ defmodule AshAdmin.MixProject do
defp deps do
[
{:ash, "~> 1.36 and >= 1.36.18"},
{:ash_phoenix, "~> 0.4 and >= 0.4.4"},
# {:ash_phoenix, "~> 0.4 and >= 0.4.4"},
{:ash_phoenix, path: "../ash_phoenix"},
{:surface, "~> 0.3.1"},
{:phoenix_live_view, "~> 0.15.4"},
{:phoenix_html, "~> 2.14.1 or ~> 2.15"},