From acfecc11ec5cc2795282ec1ffe620a919916d4c8 Mon Sep 17 00:00:00 2001 From: Jamil Date: Mon, 27 Jan 2025 09:38:19 -0800 Subject: [PATCH] feat(portal): Sort resources by name ASC by default (#7884) Updates the Resource's pagination cursor such that the default cursor (with no HTTP params applied) uses `{:resources, :asc, :name}` as the default, which correctly updates all Resources live tables to sort by `name`. The reason this is updated at the Query layer is because I wanted to achieve this without populating URL params by default, and still allowing the sort icon to properly reflect the default sort order upon page load, which it does. My initial attempt went down the path of updating `assign_live_table/3` to take a `default_order_by` option. That didn't work because upon page load we `handle_params` which resets the ordering immediately based on the URL params. Rather than update the UI code to track even more state in order to use `default_order_by` when the `order_by` param is not specified, I opted to updated the Query module instead which the UI uses. Fixes #7842 --- .../lib/domain/resources/resource/query.ex | 1 + ...20250127165930_index_resources_on_name.exs | 13 +++++++ .../test/web/live/resources/index_test.exs | 38 +++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 elixir/apps/domain/priv/repo/migrations/20250127165930_index_resources_on_name.exs diff --git a/elixir/apps/domain/lib/domain/resources/resource/query.ex b/elixir/apps/domain/lib/domain/resources/resource/query.ex index 00a2f6f9d..d40e5ea82 100644 --- a/elixir/apps/domain/lib/domain/resources/resource/query.ex +++ b/elixir/apps/domain/lib/domain/resources/resource/query.ex @@ -142,6 +142,7 @@ defmodule Domain.Resources.Resource.Query do @impl Domain.Repo.Query def cursor_fields, do: [ + {:resources, :asc, :name}, {:resources, :asc, :inserted_at}, {:resources, :asc, :id} ] diff --git a/elixir/apps/domain/priv/repo/migrations/20250127165930_index_resources_on_name.exs b/elixir/apps/domain/priv/repo/migrations/20250127165930_index_resources_on_name.exs new file mode 100644 index 000000000..6fd1b5810 --- /dev/null +++ b/elixir/apps/domain/priv/repo/migrations/20250127165930_index_resources_on_name.exs @@ -0,0 +1,13 @@ +defmodule Domain.Repo.Migrations.IndexResourcesOnName do + use Ecto.Migration + + def change do + create( + index( + :resources, + [:account_id, :name], + where: "deleted_at IS NULL" + ) + ) + end +end diff --git a/elixir/apps/web/test/web/live/resources/index_test.exs b/elixir/apps/web/test/web/live/resources/index_test.exs index 998518519..3efddacf3 100644 --- a/elixir/apps/web/test/web/live/resources/index_test.exs +++ b/elixir/apps/web/test/web/live/resources/index_test.exs @@ -100,6 +100,44 @@ defmodule Web.Live.Resources.IndexTest do end) end + test "sort alphabetically by name ASC by default", %{ + account: account, + identity: identity, + conn: conn + } do + resource5 = Fixtures.Resources.create_resource(account: account, name: "Resource 5") + resource4 = Fixtures.Resources.create_resource(account: account, name: "Resource 4") + resource3 = Fixtures.Resources.create_resource(account: account, name: "Resource 3") + resource2 = Fixtures.Resources.create_resource(account: account, name: "Resource 2") + resource1 = Fixtures.Resources.create_resource(account: account, name: "Resource 1") + + {:ok, lv, _html} = + conn + |> authorize_conn(identity) + |> live(~p"/#{account}/resources") + + resource_rows = + lv + |> element("#resources") + |> render() + |> table_to_map() + + first_row = Enum.at(resource_rows, 0) + assert first_row["name"] =~ resource1.name + + second_row = Enum.at(resource_rows, 1) + assert second_row["name"] =~ resource2.name + + third_row = Enum.at(resource_rows, 2) + assert third_row["name"] =~ resource3.name + + fourth_row = Enum.at(resource_rows, 3) + assert fourth_row["name"] =~ resource4.name + + fifth_row = Enum.at(resource_rows, 4) + assert fifth_row["name"] =~ resource5.name + end + test "renders authorized groups peek", %{ account: account, identity: identity,