mirror of
https://github.com/ash-project/ash_admin.git
synced 2024-09-19 12:53:28 +12:00
parent
50c87b30ef
commit
afcc7ae266
6 changed files with 253 additions and 16 deletions
21
dev/repo/migrations/20240522034001_migrate_resources7.exs
Normal file
21
dev/repo/migrations/20240522034001_migrate_resources7.exs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
defmodule Demo.Repo.Migrations.MigrateResources7 do
|
||||||
|
@moduledoc """
|
||||||
|
Updates resources based on their most recent snapshots.
|
||||||
|
|
||||||
|
This file was autogenerated with `mix ash_postgres.generate_migrations`
|
||||||
|
"""
|
||||||
|
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def up do
|
||||||
|
alter table(:tickets) do
|
||||||
|
add(:metadatas, {:array, :map})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def down do
|
||||||
|
alter table(:tickets) do
|
||||||
|
remove(:metadatas)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
196
dev/resource_snapshots/repo/tickets/20240522034001.json
Normal file
196
dev/resource_snapshots/repo/tickets/20240522034001.json
Normal file
|
@ -0,0 +1,196 @@
|
||||||
|
{
|
||||||
|
"attributes": [
|
||||||
|
{
|
||||||
|
"default": "fragment(\"gen_random_uuid()\")",
|
||||||
|
"size": null,
|
||||||
|
"type": "uuid",
|
||||||
|
"source": "id",
|
||||||
|
"references": null,
|
||||||
|
"allow_nil?": false,
|
||||||
|
"generated?": false,
|
||||||
|
"primary_key?": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "nil",
|
||||||
|
"size": null,
|
||||||
|
"type": "text",
|
||||||
|
"source": "subject",
|
||||||
|
"references": null,
|
||||||
|
"allow_nil?": false,
|
||||||
|
"generated?": false,
|
||||||
|
"primary_key?": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "nil",
|
||||||
|
"size": null,
|
||||||
|
"type": "map",
|
||||||
|
"source": "metadata",
|
||||||
|
"references": null,
|
||||||
|
"allow_nil?": true,
|
||||||
|
"generated?": false,
|
||||||
|
"primary_key?": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "nil",
|
||||||
|
"size": null,
|
||||||
|
"type": [
|
||||||
|
"array",
|
||||||
|
"map"
|
||||||
|
],
|
||||||
|
"source": "metadatas",
|
||||||
|
"references": null,
|
||||||
|
"allow_nil?": true,
|
||||||
|
"generated?": false,
|
||||||
|
"primary_key?": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "nil",
|
||||||
|
"size": null,
|
||||||
|
"type": "text",
|
||||||
|
"source": "description",
|
||||||
|
"references": null,
|
||||||
|
"allow_nil?": true,
|
||||||
|
"generated?": false,
|
||||||
|
"primary_key?": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "nil",
|
||||||
|
"size": null,
|
||||||
|
"type": "text",
|
||||||
|
"source": "response",
|
||||||
|
"references": null,
|
||||||
|
"allow_nil?": true,
|
||||||
|
"generated?": false,
|
||||||
|
"primary_key?": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "\"new\"",
|
||||||
|
"size": null,
|
||||||
|
"type": "text",
|
||||||
|
"source": "status",
|
||||||
|
"references": null,
|
||||||
|
"allow_nil?": false,
|
||||||
|
"generated?": false,
|
||||||
|
"primary_key?": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "fragment(\"(now() AT TIME ZONE 'utc')\")",
|
||||||
|
"size": null,
|
||||||
|
"type": "utc_datetime_usec",
|
||||||
|
"source": "inserted_at",
|
||||||
|
"references": null,
|
||||||
|
"allow_nil?": false,
|
||||||
|
"generated?": false,
|
||||||
|
"primary_key?": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "fragment(\"(now() AT TIME ZONE 'utc')\")",
|
||||||
|
"size": null,
|
||||||
|
"type": "utc_datetime_usec",
|
||||||
|
"source": "updated_at",
|
||||||
|
"references": null,
|
||||||
|
"allow_nil?": false,
|
||||||
|
"generated?": false,
|
||||||
|
"primary_key?": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "nil",
|
||||||
|
"size": null,
|
||||||
|
"type": "uuid",
|
||||||
|
"source": "reporter_id",
|
||||||
|
"references": {
|
||||||
|
"name": "tickets_reporter_id_fkey",
|
||||||
|
"table": "users",
|
||||||
|
"schema": "public",
|
||||||
|
"multitenancy": {
|
||||||
|
"global": null,
|
||||||
|
"attribute": null,
|
||||||
|
"strategy": null
|
||||||
|
},
|
||||||
|
"on_update": null,
|
||||||
|
"primary_key?": true,
|
||||||
|
"on_delete": null,
|
||||||
|
"destination_attribute": "id",
|
||||||
|
"deferrable": false,
|
||||||
|
"match_type": null,
|
||||||
|
"match_with": null,
|
||||||
|
"destination_attribute_default": null,
|
||||||
|
"destination_attribute_generated": null
|
||||||
|
},
|
||||||
|
"allow_nil?": true,
|
||||||
|
"generated?": false,
|
||||||
|
"primary_key?": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "nil",
|
||||||
|
"size": null,
|
||||||
|
"type": "uuid",
|
||||||
|
"source": "representative_id",
|
||||||
|
"references": {
|
||||||
|
"name": "tickets_representative_id_fkey",
|
||||||
|
"table": "users",
|
||||||
|
"schema": "public",
|
||||||
|
"multitenancy": {
|
||||||
|
"global": null,
|
||||||
|
"attribute": null,
|
||||||
|
"strategy": null
|
||||||
|
},
|
||||||
|
"on_update": null,
|
||||||
|
"primary_key?": true,
|
||||||
|
"on_delete": null,
|
||||||
|
"destination_attribute": "id",
|
||||||
|
"deferrable": false,
|
||||||
|
"match_type": null,
|
||||||
|
"match_with": null,
|
||||||
|
"destination_attribute_default": null,
|
||||||
|
"destination_attribute_generated": null
|
||||||
|
},
|
||||||
|
"allow_nil?": true,
|
||||||
|
"generated?": false,
|
||||||
|
"primary_key?": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "nil",
|
||||||
|
"size": null,
|
||||||
|
"type": "uuid",
|
||||||
|
"source": "organization_id",
|
||||||
|
"references": {
|
||||||
|
"name": "tickets_organization_id_fkey",
|
||||||
|
"table": "organizations",
|
||||||
|
"schema": "public",
|
||||||
|
"multitenancy": {
|
||||||
|
"global": null,
|
||||||
|
"attribute": null,
|
||||||
|
"strategy": null
|
||||||
|
},
|
||||||
|
"on_update": null,
|
||||||
|
"primary_key?": true,
|
||||||
|
"on_delete": null,
|
||||||
|
"destination_attribute": "id",
|
||||||
|
"deferrable": false,
|
||||||
|
"match_type": null,
|
||||||
|
"match_with": null,
|
||||||
|
"destination_attribute_default": null,
|
||||||
|
"destination_attribute_generated": null
|
||||||
|
},
|
||||||
|
"allow_nil?": false,
|
||||||
|
"generated?": false,
|
||||||
|
"primary_key?": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"table": "tickets",
|
||||||
|
"hash": "3DE3CF59D6C0732CC835F8ACD8D68541934549BB9086EDAC65177EDF6A62FECA",
|
||||||
|
"repo": "Elixir.Demo.Repo",
|
||||||
|
"schema": null,
|
||||||
|
"identities": [],
|
||||||
|
"multitenancy": {
|
||||||
|
"global": null,
|
||||||
|
"attribute": null,
|
||||||
|
"strategy": null
|
||||||
|
},
|
||||||
|
"base_filter": null,
|
||||||
|
"check_constraints": [],
|
||||||
|
"custom_indexes": [],
|
||||||
|
"custom_statements": [],
|
||||||
|
"has_create_action": true
|
||||||
|
}
|
|
@ -69,7 +69,7 @@ defmodule Demo.Tickets.Ticket do
|
||||||
end
|
end
|
||||||
|
|
||||||
create :open do
|
create :open do
|
||||||
accept [:subject, :metadata]
|
accept [:subject, :metadata, :metadatas]
|
||||||
primary? true
|
primary? true
|
||||||
argument :representative, :map, allow_nil?: false
|
argument :representative, :map, allow_nil?: false
|
||||||
argument :organization, :map, allow_nil?: false
|
argument :organization, :map, allow_nil?: false
|
||||||
|
@ -146,6 +146,10 @@ defmodule Demo.Tickets.Ticket do
|
||||||
public? true
|
public? true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
attribute :metadatas, {:array, Demo.Tickets.Ticket.Types.Metadata} do
|
||||||
|
public? true
|
||||||
|
end
|
||||||
|
|
||||||
attribute :description, :string do
|
attribute :description, :string do
|
||||||
public? true
|
public? true
|
||||||
end
|
end
|
||||||
|
|
|
@ -326,7 +326,7 @@ defmodule AshAdmin.CoreComponents do
|
||||||
<select
|
<select
|
||||||
id={@id}
|
id={@id}
|
||||||
name={@name}
|
name={@name}
|
||||||
class="mt-2 block rounded-md border border-gray-300 bg-white shadow-sm focus:border-zinc-400 focus:ring-0 sm:text-sm"
|
class="mt-2 block w-full rounded-md border border-gray-300 bg-white shadow-sm focus:border-zinc-400 focus:ring-0 sm:text-sm"
|
||||||
multiple={@multiple}
|
multiple={@multiple}
|
||||||
{@rest}
|
{@rest}
|
||||||
>
|
>
|
||||||
|
|
|
@ -971,12 +971,11 @@ defmodule AshAdmin.Components.Resource.Form do
|
||||||
<label class="block text-sm font-medium text-gray-700" for={@union_type_name}>
|
<label class="block text-sm font-medium text-gray-700" for={@union_type_name}>
|
||||||
Type
|
Type
|
||||||
</label>
|
</label>
|
||||||
<div class="w-8">
|
<div class="w-full">
|
||||||
<.input
|
<.input
|
||||||
phx-change="union-type-changed"
|
phx-change="union-type-changed"
|
||||||
name={@union_type_name}
|
name={@union_type_name}
|
||||||
type="select"
|
type="select"
|
||||||
class="w-8"
|
|
||||||
value={@actual_union_type_name}
|
value={@actual_union_type_name}
|
||||||
options={@possible_types}
|
options={@possible_types}
|
||||||
field={@form[:_union_type]}
|
field={@form[:_union_type]}
|
||||||
|
@ -1015,7 +1014,7 @@ defmodule AshAdmin.Components.Resource.Form do
|
||||||
~H"""
|
~H"""
|
||||||
<%= cond do %>
|
<%= cond do %>
|
||||||
<% match?({:array, {:array, _}}, @attribute.type) -> %>
|
<% match?({:array, {:array, _}}, @attribute.type) -> %>
|
||||||
<%= render_fallback_attribute(assigns, @form, @attribute, @value, @name, @id) %>
|
<%= render_fallback_attribute(assigns, @form, @attribute, @value, @name, @id, @union_type) %>
|
||||||
<% match?({:array, _}, @attribute.type) && Ash.Type.embedded_type?(@attribute.type) -> %>
|
<% match?({:array, _}, @attribute.type) && Ash.Type.embedded_type?(@attribute.type) -> %>
|
||||||
<.inputs_for :let={inner_form} field={@form[@attribute.name]}>
|
<.inputs_for :let={inner_form} field={@form[@attribute.name]}>
|
||||||
<.input
|
<.input
|
||||||
|
@ -1108,7 +1107,7 @@ defmodule AshAdmin.Components.Resource.Form do
|
||||||
name={@name || @form.name <> "[#{@attribute.name}]"}
|
name={@name || @form.name <> "[#{@attribute.name}]"}
|
||||||
/>
|
/>
|
||||||
<% true -> %>
|
<% true -> %>
|
||||||
<%= render_fallback_attribute(assigns, @form, @attribute, @value, @name, @id) %>
|
<%= render_fallback_attribute(assigns, @form, @attribute, @value, @name, @id, @union_type) %>
|
||||||
<% end %>
|
<% end %>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
@ -1136,7 +1135,8 @@ defmodule AshAdmin.Components.Resource.Form do
|
||||||
%{type: {:array, type}} = attribute,
|
%{type: {:array, type}} = attribute,
|
||||||
value,
|
value,
|
||||||
name,
|
name,
|
||||||
id
|
id,
|
||||||
|
union_type
|
||||||
) do
|
) do
|
||||||
name = name || form.name <> "[#{attribute.name}]"
|
name = name || form.name <> "[#{attribute.name}]"
|
||||||
id = id || form.id <> "_#{attribute.name}"
|
id = id || form.id <> "_#{attribute.name}"
|
||||||
|
@ -1148,7 +1148,8 @@ defmodule AshAdmin.Components.Resource.Form do
|
||||||
type: type,
|
type: type,
|
||||||
value: value,
|
value: value,
|
||||||
name: name,
|
name: name,
|
||||||
id: id
|
id: id,
|
||||||
|
union_type: union_type || default_union_type(type, attribute.constraints[:items] || [])
|
||||||
)
|
)
|
||||||
|
|
||||||
~H"""
|
~H"""
|
||||||
|
@ -1163,7 +1164,8 @@ defmodule AshAdmin.Components.Resource.Form do
|
||||||
@form,
|
@form,
|
||||||
{:list_value, this_value},
|
{:list_value, this_value},
|
||||||
@name <> "[#{index}]",
|
@name <> "[#{index}]",
|
||||||
@id <> "_#{index}"
|
@id <> "_#{index}",
|
||||||
|
@union_type
|
||||||
) %>
|
) %>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
@ -1183,6 +1185,7 @@ defmodule AshAdmin.Components.Resource.Form do
|
||||||
phx-target={@myself}
|
phx-target={@myself}
|
||||||
phx-value-path={@form.name}
|
phx-value-path={@form.name}
|
||||||
phx-value-field={@attribute.name}
|
phx-value-field={@attribute.name}
|
||||||
|
phx-value-union-type={@union_type}
|
||||||
class="flex h-6 w-6 mt-2 border-gray-600 hover:bg-gray-400 rounded-md justify-center items-center"
|
class="flex h-6 w-6 mt-2 border-gray-600 hover:bg-gray-400 rounded-md justify-center items-center"
|
||||||
>
|
>
|
||||||
<.icon name="hero-plus" class="h-4 w-4 text-gray-500" />
|
<.icon name="hero-plus" class="h-4 w-4 text-gray-500" />
|
||||||
|
@ -1191,7 +1194,7 @@ defmodule AshAdmin.Components.Resource.Form do
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
defp render_fallback_attribute(assigns, form, attribute, value, name, id) do
|
defp render_fallback_attribute(assigns, form, attribute, value, name, id, _union_type) do
|
||||||
casted_value =
|
casted_value =
|
||||||
case value(value, form, attribute) do
|
case value(value, form, attribute) do
|
||||||
%AshPhoenix.Form{resource: AshPhoenix.Form.WrappedValue} = form ->
|
%AshPhoenix.Form{resource: AshPhoenix.Form.WrappedValue} = form ->
|
||||||
|
@ -1254,6 +1257,16 @@ defmodule AshAdmin.Components.Resource.Form do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp default_union_type(Ash.Type.Union, constraints) do
|
||||||
|
constraints[:types]
|
||||||
|
|> List.wrap()
|
||||||
|
|> Enum.at(0)
|
||||||
|
|> elem(0)
|
||||||
|
|> to_string()
|
||||||
|
end
|
||||||
|
|
||||||
|
defp default_union_type(_, _), do: nil
|
||||||
|
|
||||||
defp non_nil_form_field(_form, []), do: nil
|
defp non_nil_form_field(_form, []), do: nil
|
||||||
|
|
||||||
defp non_nil_form_field(form, [field | rest]) do
|
defp non_nil_form_field(form, [field | rest]) do
|
||||||
|
@ -1480,13 +1493,20 @@ defmodule AshAdmin.Components.Resource.Form do
|
||||||
|> assign(:form, form)}
|
|> assign(:form, form)}
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_event("append_value", %{"path" => path, "field" => field}, socket) do
|
def handle_event("append_value", %{"path" => path, "field" => field} = params, socket) do
|
||||||
|
to_append =
|
||||||
|
case params["union-type"] do
|
||||||
|
nil -> nil
|
||||||
|
value when value != "" -> %{"_union_type" => value}
|
||||||
|
_ -> nil
|
||||||
|
end
|
||||||
|
|
||||||
list =
|
list =
|
||||||
AshPhoenix.Form.get_form(socket.assigns.form, path)
|
AshPhoenix.Form.get_form(socket.assigns.form, path)
|
||||||
|> AshPhoenix.Form.value(String.to_existing_atom(field))
|
|> AshPhoenix.Form.value(String.to_existing_atom(field))
|
||||||
|> Kernel.||([])
|
|> Kernel.||([])
|
||||||
|> indexed_list()
|
|> indexed_list()
|
||||||
|> append_to_and_map(nil)
|
|> append_to_and_map(to_append)
|
||||||
|
|
||||||
params =
|
params =
|
||||||
put_in_creating(
|
put_in_creating(
|
||||||
|
|
|
@ -1290,10 +1290,6 @@ select {
|
||||||
width: 1.5rem;
|
width: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.w-8 {
|
|
||||||
width: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.w-80 {
|
.w-80 {
|
||||||
width: 20rem;
|
width: 20rem;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue