Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* text=auto eol=lf
12 changes: 11 additions & 1 deletion REUSE.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
version = 1

[[annotations]]
path = ["REUSE.toml", "priv/static/assets/app*"]
path = ["REUSE.toml", ".gitattributes", "priv/static/assets/app*"]
SPDX-FileCopyrightText = "2020 Zach Daniel"
SPDX-License-Identifier = "MIT"

Expand All @@ -14,6 +14,16 @@ path = "assets/vendor/topbar.js"
SPDX-FileCopyrightText = "2021 Buu Nguyen"
SPDX-License-Identifier = "MIT"

[[annotations]]
path = "assets/vendor/sortable.js"
SPDX-FileCopyrightText = "SortableJS contributors <https://github.com/SortableJS/Sortable>"
SPDX-License-Identifier = "MIT"

[[annotations]]
path = ["assets/package.json", "assets/package-lock.json"]
SPDX-FileCopyrightText = "2020 ash_admin contributors <https://github.com/ash-project/ash_admin/graphs/contributors>"
SPDX-License-Identifier = "MIT"

[[annotations]]
path = ["assets/vendor/heroicons/*", "assets/vendor/heroicons/**/*"]
SPDX-FileCopyrightText = "2020 Refactoring UI Inc"
Expand Down
12 changes: 12 additions & 0 deletions assets/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,18 @@ main.admin-main::after {
height: 4rem;
}

/* Sortable.js drag-and-drop for array fields */

/* placeholder element is slightly transparent */
.sortable-ghost {
opacity: 0.4;
}

/* draggable element is styled to indicate it's being dragged */
.sortable-drag {
cursor: grabbing;
}

/* CodeMirror 6 editor styling */
.cm-editor {
min-height: 200px;
Expand Down
35 changes: 35 additions & 0 deletions assets/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
// SPDX-License-Identifier: MIT

import topbar from "../vendor/topbar";
// vendored Sortable.js for drag-and-drop reordering of primitive array fields
import Sortable from "../vendor/sortable";
import {
EditorView, keymap, lineNumbers, highlightActiveLineGutter,
highlightSpecialChars, drawSelection, dropCursor, rectangularSelection,
Expand Down Expand Up @@ -345,6 +347,39 @@ Hooks.MaintainAttrs = {
},
};

// Sortable.js drag-and-drop for array fields
Hooks.Sortable = {
// initialize Sortable on the array container when the LiveView hook mounts
mounted() {
this.sortable = new Sortable(this.el, {
animation: 150,
draggable: '[data-sortable="true"]',
handle: '[data-sort-handle="true"]',
ghostClass: "sortable-ghost",
dragClass: "sortable-drag",
forceFallback: true,
// after a drop, send the new row order to the server
onEnd: () => {
const indices = Array.from(
this.el.querySelectorAll('[data-sortable="true"]')
).map((el) => el.dataset.sortIndex);
if (indices.length < 2) return;
this.pushEventTo(this.el, "update_array_sorting", {
path: this.el.dataset.path,
field: this.el.dataset.field,
indices: indices,
});
},
});
},
// tear down the Sortable instance when the hook is destroyed
destroyed() {
if (this.sortable) {
this.sortable.destroy();
}
},
};

Hooks.Typeahead = {
mounted() {
this.aborter = new AbortController();
Expand Down
17 changes: 14 additions & 3 deletions assets/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions assets/vendor/sortable.js

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions assets/vendor/sortable.js.license
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
SPDX-FileCopyrightText: SortableJS contributors <https://github.com/SortableJS/Sortable>

SPDX-License-Identifier: MIT
9 changes: 9 additions & 0 deletions dev/resources/accounts/resources/calculator.ex
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,14 @@ defmodule Demo.Accounts.Calculator do
:ok
end
end

# demo: primitive array arg for drag-and-drop sorting in GenericAction forms
action :echo_tags, {:array, :string} do
argument :tags, {:array, :string}, allow_nil?: true, public?: true

run fn input, _ ->
{:ok, List.wrap(input.arguments[:tags])}
end
end
end
end
15 changes: 12 additions & 3 deletions dev/resources/accounts/resources/user.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,14 @@ defmodule Demo.Accounts.User do
end

show_action :read
read_actions [:me, :read, :by_id, :by_name]
read_actions [:me, :read, :by_id, :by_name, :filter_by_tags]

table_columns [:id, :first_name, :last_name, :representative, :admin, :full_name, :api_key, :date_of_birth]
table_filterable_columns [:first_name]
table_sortable_columns [:first_name, :last_name]

show_calculations [:multi_arguments, :is_super_admin?, :full_name, :nested_embed]
show_calculations [:multi_arguments, :is_super_admin?, :full_name, :nested_embed, :join_tags]
end

multitenancy do
strategy :attribute
attribute :org
Expand Down Expand Up @@ -67,6 +66,11 @@ defmodule Demo.Accounts.User do
filter expr(first_name == ^arg(:first_name) and last_name == ^arg(:last_name))
end

# demo: primitive array arg for drag-and-drop sorting in DataTable query forms
read :filter_by_tags do
argument :tags, {:array, :string}, allow_nil?: true, public?: true
end

create :create do
argument :offices, {:array, :map}
change manage_relationship(:offices, type: :append)
Expand Down Expand Up @@ -126,6 +130,11 @@ defmodule Demo.Accounts.User do
calculate :nested_embed, :string, expr(tags) do
argument :nested_embed, Demo.Accounts.NestedEmbed, allow_nil?: false
end

# demo: primitive array arg for drag-and-drop sorting on Show calculation forms
calculate :join_tags, :string, expr("") do
argument :tags, {:array, :string}, allow_nil?: true
end
end

attributes do
Expand Down
39 changes: 37 additions & 2 deletions lib/ash_admin/components/resource/data_table.ex
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,11 @@ defmodule AshAdmin.Components.Resource.DataTable do
end

def handle_event("validate", %{"query" => query}, socket) do
query = AshPhoenix.Form.validate(socket.assigns.query, query)
query =
AshPhoenix.Form.validate(
socket.assigns.query,
AshAdmin.Helpers.sanitize_form_params(query)
)

{:noreply, assign(socket, query: query)}
end
Expand All @@ -363,7 +367,10 @@ defmodule AshAdmin.Components.Resource.DataTable do
{:noreply,
push_navigate(
socket,
to: self_path(socket.assigns.url_path, socket.assigns.params, %{"args" => query_params})
to:
self_path(socket.assigns.url_path, socket.assigns.params, %{
"args" => AshAdmin.Helpers.sanitize_form_params(query_params)
})
)}
end

Expand Down Expand Up @@ -434,6 +441,23 @@ defmodule AshAdmin.Components.Resource.DataTable do
|> assign(:query, query)}
end

def handle_event(
"update_array_sorting",
%{"path" => path, "field" => field, "indices" => indices},
socket
) do
query =
AshPhoenix.Form.update_form(
socket.assigns.query,
path,
&sort_array_value(&1, field, indices)
)

{:noreply,
socket
|> assign(:query, query)}
end

defp indexed_list(map) when is_map(map) do
map
|> Map.keys()
Expand Down Expand Up @@ -502,6 +526,17 @@ defmodule AshAdmin.Components.Resource.DataTable do
AshPhoenix.Form.validate(form, new_params)
end

defp sort_array_value(form, field, indices) do
new_value =
form
|> AshPhoenix.Form.value(String.to_existing_atom(field))
|> reorder_by_indices(indices)

new_params = Map.put(form.params, field, new_value)

AshPhoenix.Form.validate(form, new_params)
end

# Field rendering - delegate to existing Table component logic
defp render_field_value(record, field_name, assigns) do
attribute = Ash.Resource.Info.field(assigns.resource, field_name)
Expand Down
Loading