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
|
||||
|
||||
create :open do
|
||||
accept [:subject, :metadata]
|
||||
accept [:subject, :metadata, :metadatas]
|
||||
primary? true
|
||||
argument :representative, :map, allow_nil?: false
|
||||
argument :organization, :map, allow_nil?: false
|
||||
|
@ -146,6 +146,10 @@ defmodule Demo.Tickets.Ticket do
|
|||
public? true
|
||||
end
|
||||
|
||||
attribute :metadatas, {:array, Demo.Tickets.Ticket.Types.Metadata} do
|
||||
public? true
|
||||
end
|
||||
|
||||
attribute :description, :string do
|
||||
public? true
|
||||
end
|
||||
|
|
|
@ -326,7 +326,7 @@ defmodule AshAdmin.CoreComponents do
|
|||
<select
|
||||
id={@id}
|
||||
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}
|
||||
{@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}>
|
||||
Type
|
||||
</label>
|
||||
<div class="w-8">
|
||||
<div class="w-full">
|
||||
<.input
|
||||
phx-change="union-type-changed"
|
||||
name={@union_type_name}
|
||||
type="select"
|
||||
class="w-8"
|
||||
value={@actual_union_type_name}
|
||||
options={@possible_types}
|
||||
field={@form[:_union_type]}
|
||||
|
@ -1015,7 +1014,7 @@ defmodule AshAdmin.Components.Resource.Form do
|
|||
~H"""
|
||||
<%= cond do %>
|
||||
<% 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) -> %>
|
||||
<.inputs_for :let={inner_form} field={@form[@attribute.name]}>
|
||||
<.input
|
||||
|
@ -1108,7 +1107,7 @@ defmodule AshAdmin.Components.Resource.Form do
|
|||
name={@name || @form.name <> "[#{@attribute.name}]"}
|
||||
/>
|
||||
<% true -> %>
|
||||
<%= render_fallback_attribute(assigns, @form, @attribute, @value, @name, @id) %>
|
||||
<%= render_fallback_attribute(assigns, @form, @attribute, @value, @name, @id, @union_type) %>
|
||||
<% end %>
|
||||
"""
|
||||
end
|
||||
|
@ -1136,7 +1135,8 @@ defmodule AshAdmin.Components.Resource.Form do
|
|||
%{type: {:array, type}} = attribute,
|
||||
value,
|
||||
name,
|
||||
id
|
||||
id,
|
||||
union_type
|
||||
) do
|
||||
name = name || form.name <> "[#{attribute.name}]"
|
||||
id = id || form.id <> "_#{attribute.name}"
|
||||
|
@ -1148,7 +1148,8 @@ defmodule AshAdmin.Components.Resource.Form do
|
|||
type: type,
|
||||
value: value,
|
||||
name: name,
|
||||
id: id
|
||||
id: id,
|
||||
union_type: union_type || default_union_type(type, attribute.constraints[:items] || [])
|
||||
)
|
||||
|
||||
~H"""
|
||||
|
@ -1163,7 +1164,8 @@ defmodule AshAdmin.Components.Resource.Form do
|
|||
@form,
|
||||
{:list_value, this_value},
|
||||
@name <> "[#{index}]",
|
||||
@id <> "_#{index}"
|
||||
@id <> "_#{index}",
|
||||
@union_type
|
||||
) %>
|
||||
<button
|
||||
type="button"
|
||||
|
@ -1183,6 +1185,7 @@ defmodule AshAdmin.Components.Resource.Form do
|
|||
phx-target={@myself}
|
||||
phx-value-path={@form.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"
|
||||
>
|
||||
<.icon name="hero-plus" class="h-4 w-4 text-gray-500" />
|
||||
|
@ -1191,7 +1194,7 @@ defmodule AshAdmin.Components.Resource.Form do
|
|||
"""
|
||||
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 =
|
||||
case value(value, form, attribute) do
|
||||
%AshPhoenix.Form{resource: AshPhoenix.Form.WrappedValue} = form ->
|
||||
|
@ -1254,6 +1257,16 @@ defmodule AshAdmin.Components.Resource.Form do
|
|||
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, [field | rest]) do
|
||||
|
@ -1480,13 +1493,20 @@ defmodule AshAdmin.Components.Resource.Form do
|
|||
|> assign(:form, form)}
|
||||
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 =
|
||||
AshPhoenix.Form.get_form(socket.assigns.form, path)
|
||||
|> AshPhoenix.Form.value(String.to_existing_atom(field))
|
||||
|> Kernel.||([])
|
||||
|> indexed_list()
|
||||
|> append_to_and_map(nil)
|
||||
|> append_to_and_map(to_append)
|
||||
|
||||
params =
|
||||
put_in_creating(
|
||||
|
|
|
@ -1290,10 +1290,6 @@ select {
|
|||
width: 1.5rem;
|
||||
}
|
||||
|
||||
.w-8 {
|
||||
width: 2rem;
|
||||
}
|
||||
|
||||
.w-80 {
|
||||
width: 20rem;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue