From 987e1e6672803c1e1ad13051e26fed9bcdf7a312 Mon Sep 17 00:00:00 2001 From: Phil-Bastian Berndt Date: Thu, 14 Nov 2024 20:39:05 +0100 Subject: [PATCH 01/23] remove adapter specific bang function --- lib/backpex/adapter.ex | 9 +-------- lib/backpex/adapters/ash.ex | 15 --------------- lib/backpex/adapters/ecto.ex | 17 +---------------- lib/backpex/exceptions.ex | 13 +++---------- lib/backpex/live_resource.ex | 2 +- lib/backpex/resource.ex | 18 ++++++++++-------- 6 files changed, 16 insertions(+), 58 deletions(-) diff --git a/lib/backpex/adapter.ex b/lib/backpex/adapter.ex index 9ce14231..544c0af6 100644 --- a/lib/backpex/adapter.ex +++ b/lib/backpex/adapter.ex @@ -27,14 +27,7 @@ defmodule Backpex.Adapter do Should return `nil` if no result was found. """ - @callback get(term(), term(), term()) :: term() - - @doc """ - Gets a database record with the given primary key value. - - Should raise an exception if no result was found. - """ - @callback get!(term(), term(), term()) :: term() + @callback get(term(), map(), module()) :: {:ok, struct() | nil} | {:error, term()} @doc """ Returns a list of items by given criteria. diff --git a/lib/backpex/adapters/ash.ex b/lib/backpex/adapters/ash.ex index fb605fcb..727cbc84 100644 --- a/lib/backpex/adapters/ash.ex +++ b/lib/backpex/adapters/ash.ex @@ -38,21 +38,6 @@ if Code.ensure_loaded?(Ash) do |> Ash.read_one() end - @doc """ - Gets a database record with the given primary key value. - - Raises an error if no record was found. - """ - @impl Backpex.Adapter - def get!(primary_value, _assigns, live_resource) do - config = live_resource.config(:adapter_config) - primary_key = live_resource.config(:primary_key) - - config[:resource] - |> Ash.Query.filter(^Ash.Expr.ref(primary_key) == ^primary_value) - |> Ash.read_one!() - end - @doc """ Returns a list of items by given criteria. """ diff --git a/lib/backpex/adapters/ecto.ex b/lib/backpex/adapters/ecto.ex index d02742c7..c2f9ef0d 100644 --- a/lib/backpex/adapters/ecto.ex +++ b/lib/backpex/adapters/ecto.ex @@ -66,8 +66,6 @@ defmodule Backpex.Adapters.Ecto do @doc """ Gets a database record with the given primary key value. - - Returns `nil` if no result was found. """ @impl Backpex.Adapter def get(primary_value, assigns, live_resource) do @@ -76,20 +74,7 @@ defmodule Backpex.Adapters.Ecto do record_query(primary_value, config[:schema], item_query, live_resource) |> config[:repo].one() - end - - @doc """ - Gets a database record with the given primary key value. - - Raises `Ecto.NoResultsError` if no record was found. - """ - @impl Backpex.Adapter - def get!(primary_value, assigns, live_resource) do - config = live_resource.config(:adapter_config) - item_query = prepare_item_query(config, assigns) - - record_query(primary_value, config[:schema], item_query, live_resource) - |> config[:repo].one!() + |> then(fn result -> {:ok, result} end) end @doc """ diff --git a/lib/backpex/exceptions.ex b/lib/backpex/exceptions.ex index a75fbda0..f5d78cde 100644 --- a/lib/backpex/exceptions.ex +++ b/lib/backpex/exceptions.ex @@ -1,16 +1,9 @@ -defmodule Backpex.NoResourceError do +defmodule Backpex.NoResultsError do @moduledoc """ - Raised when resource can not be found. - - If you are seeing this error, you should check if you provided the correct identifier for the requested resource. + Raised when no results can be found. """ - defexception message: "Resource not found", plug_status: 404 - - def exception(opts) do - name = Keyword.fetch!(opts, :name) - %__MODULE__{message: "no resource found for:\n\n#{inspect(name)}"} - end + defexception message: "No results could be found", plug_status: 404 end defmodule Backpex.ForbiddenError do diff --git a/lib/backpex/live_resource.ex b/lib/backpex/live_resource.ex index cf1a2ec6..a0d48eb4 100644 --- a/lib/backpex/live_resource.ex +++ b/lib/backpex/live_resource.ex @@ -1140,7 +1140,7 @@ defmodule Backpex.LiveResource do %{live_resource: live_resource, live_action: live_action} = socket.assigns item_primary_value = primary_value(socket, item) - item = Resource.get(item_primary_value, socket.assigns, live_resource) + {:ok, item} = Resource.get(item_primary_value, socket.assigns, live_resource) socket = cond do diff --git a/lib/backpex/resource.ex b/lib/backpex/resource.ex index 5c0ce27a..c064e2db 100644 --- a/lib/backpex/resource.ex +++ b/lib/backpex/resource.ex @@ -40,7 +40,7 @@ defmodule Backpex.Resource do @doc """ Gets a database record with the given `fields` by the given `primary_value`. - Raises `Ecto.NoResultsError` if no record was found. + Returns `{:ok, nil}` if no result was found. ## Parameters @@ -48,16 +48,16 @@ defmodule Backpex.Resource do * `assigns` (map): The current assigns of the socket. * `live_resource` (module): The `Backpex.LiveResource` module. """ - def get!(primary_value, assigns, live_resource) do + def get(primary_value, assigns, live_resource) do adapter = live_resource.config(:adapter) - adapter.get!(primary_value, assigns, live_resource) + adapter.get(primary_value, assigns, live_resource) end @doc """ Gets a database record with the given `fields` by the given `primary_value`. - Returns `nil` if no result was found. + Raises `Backpex.NoResultsError` if no record was found. ## Parameters @@ -65,10 +65,12 @@ defmodule Backpex.Resource do * `assigns` (map): The current assigns of the socket. * `live_resource` (module): The `Backpex.LiveResource` module. """ - def get(primary_value, assigns, live_resource) do - adapter = live_resource.config(:adapter) - - adapter.get!(primary_value, assigns, live_resource) + def get!(primary_value, assigns, live_resource) do + case get(primary_value, assigns, live_resource) do + {:ok, nil} -> raise Backpex.NoResultsError + {:ok, result} -> result + {:error, _error} -> raise Backpex.NoResultsError + end end @doc """ From 40822a0c4e5c5f616b8c58d69c1589cfe43ec1bf Mon Sep 17 00:00:00 2001 From: Phil-Bastian Berndt Date: Fri, 17 Jan 2025 12:43:03 +0100 Subject: [PATCH 02/23] simplify docs --- lib/backpex/resource.ex | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/lib/backpex/resource.ex b/lib/backpex/resource.ex index f0de18c3..baf55255 100644 --- a/lib/backpex/resource.ex +++ b/lib/backpex/resource.ex @@ -55,15 +55,7 @@ defmodule Backpex.Resource do end @doc """ - Gets a database record with the given `fields` by the given `primary_value`. - - Raises `Backpex.NoResultsError` if no record was found. - - ## Parameters - - * `primary_value`: The identifier for the specific item to be fetched. - * `assigns` (map): The current assigns of the socket. - * `live_resource` (module): The `Backpex.LiveResource` module. + Same as `get/3` but returns the result or raises an error. """ def get!(primary_value, assigns, live_resource) do case get(primary_value, assigns, live_resource) do From 6c8ca6634b2fd2cd912456163a358613a21005e0 Mon Sep 17 00:00:00 2001 From: Phil-Bastian Berndt Date: Fri, 17 Jan 2025 12:45:00 +0100 Subject: [PATCH 03/23] fix dockerfile casing --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 1fbc90f9..320ca6df 100644 --- a/Dockerfile +++ b/Dockerfile @@ -72,7 +72,7 @@ EXPOSE 4000 # Stage: release ######################################################################## -FROM builder as release +FROM builder AS release ENV MIX_ENV=prod From 84505e06ef1087b1bb738f502dae6551a7f01ae9 Mon Sep 17 00:00:00 2001 From: Phil-Bastian Berndt Date: Fri, 17 Jan 2025 12:51:34 +0100 Subject: [PATCH 04/23] improve ash info --- demo/lib/demo_web/live/ticket_live.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/demo/lib/demo_web/live/ticket_live.ex b/demo/lib/demo_web/live/ticket_live.ex index 66ec4bbf..d8bdbcac 100644 --- a/demo/lib/demo_web/live/ticket_live.ex +++ b/demo/lib/demo_web/live/ticket_live.ex @@ -24,8 +24,8 @@ defmodule DemoWeb.TicketLive do

This resource uses the Ash adapter, which is currently in a very early alpha stage. - Currently, only index and show are functional in a very basic form. - We are working on supporting more Backpex features in the future. + Currently, only index, show and delete are functional in a + very basic form. We are working on supporting more Backpex features in the future.

""" From 0264780724346265c1ff56cf659d3ce5ee35273c Mon Sep 17 00:00:00 2001 From: Phil-Bastian Berndt Date: Fri, 17 Jan 2025 12:54:57 +0100 Subject: [PATCH 05/23] remove usage of bang functions in ash adapter --- lib/backpex/adapters/ash.ex | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/backpex/adapters/ash.ex b/lib/backpex/adapters/ash.ex index 7a7b2453..7481fcc0 100644 --- a/lib/backpex/adapters/ash.ex +++ b/lib/backpex/adapters/ash.ex @@ -44,7 +44,8 @@ if Code.ensure_loaded?(Ash) do @impl Backpex.Adapter def list(_fields, _assigns, config, _criteria \\ []) do config[:resource] - |> Ash.read!() + |> Ash.read() + |> then(fn {:ok, results} -> results end) end @doc """ @@ -53,7 +54,8 @@ if Code.ensure_loaded?(Ash) do @impl Backpex.Adapter def count(_fields, _assigns, config, _criteria \\ []) do config[:resource] - |> Ash.count!() + |> Ash.count() + |> then(fn {:ok, count} -> count end) end @doc """ From c6a623c621b2af675cac9a0a0d8ae01301cadf81 Mon Sep 17 00:00:00 2001 From: Phil-Bastian Berndt Date: Fri, 17 Jan 2025 13:31:12 +0100 Subject: [PATCH 06/23] add upgrade guide for 0.10 --- guides/upgrading/v0.10.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 guides/upgrading/v0.10.md diff --git a/guides/upgrading/v0.10.md b/guides/upgrading/v0.10.md new file mode 100644 index 00000000..ec0b186a --- /dev/null +++ b/guides/upgrading/v0.10.md @@ -0,0 +1,5 @@ +# Upgrading to v0.10 + +## LiveView 1.0 + +See [phoenix_live_view changelog](https://github.com/phoenixframework/phoenix_live_view/blob/main/CHANGELOG.md) for info on how to upgrade to `1.0`. From ddb5db823703ed067b6d95a11497acbb7782bdc9 Mon Sep 17 00:00:00 2001 From: Phil-Bastian Berndt Date: Fri, 17 Jan 2025 13:49:11 +0100 Subject: [PATCH 07/23] change parameter order for adapter list and count --- guides/upgrading/v0.11.md | 7 +++++++ lib/backpex/adapters/ash.ex | 8 ++++++-- lib/backpex/adapters/ecto.ex | 12 +++++++----- lib/backpex/live_resource.ex | 15 +++++++-------- lib/backpex/resource.ex | 6 ++---- 5 files changed, 29 insertions(+), 19 deletions(-) create mode 100644 guides/upgrading/v0.11.md diff --git a/guides/upgrading/v0.11.md b/guides/upgrading/v0.11.md new file mode 100644 index 00000000..032bfa65 --- /dev/null +++ b/guides/upgrading/v0.11.md @@ -0,0 +1,7 @@ +# Upgrading to v0.11 + +## Parameter changes in core modules + +In case you are using `Backpex.Resource` or one of the `Backpex.Adapter` modules (`Backpex.Adapters.Ecto` or +`Backpex.Adapters.Ash`) directly check out the updated function definitions. This will also apply in case you built your +own adapter. diff --git a/lib/backpex/adapters/ash.ex b/lib/backpex/adapters/ash.ex index 7481fcc0..2f90f508 100644 --- a/lib/backpex/adapters/ash.ex +++ b/lib/backpex/adapters/ash.ex @@ -42,7 +42,9 @@ if Code.ensure_loaded?(Ash) do Returns a list of items by given criteria. """ @impl Backpex.Adapter - def list(_fields, _assigns, config, _criteria \\ []) do + def list(_fields, _criteria, _assigns, live_resource) do + config = live_resource.config(:adapter_config) + config[:resource] |> Ash.read() |> then(fn {:ok, results} -> results end) @@ -52,7 +54,9 @@ if Code.ensure_loaded?(Ash) do Returns the number of items matching the given criteria. """ @impl Backpex.Adapter - def count(_fields, _assigns, config, _criteria \\ []) do + def count(_fields, _criteria, _assigns, live_resource) do + config = live_resource.config(:adapter_config) + config[:resource] |> Ash.count() |> then(fn {:ok, count} -> count end) diff --git a/lib/backpex/adapters/ecto.ex b/lib/backpex/adapters/ecto.ex index f85d086d..4c20b6a6 100644 --- a/lib/backpex/adapters/ecto.ex +++ b/lib/backpex/adapters/ecto.ex @@ -81,10 +81,11 @@ defmodule Backpex.Adapters.Ecto do Returns a list of items by given criteria. """ @impl Backpex.Adapter - def list(fields, assigns, config, criteria \\ []) do + def list(fields, criteria, assigns, live_resource) do + config = live_resource.config(:adapter_config) item_query = prepare_item_query(config, assigns) - list_query(assigns, item_query, fields, criteria) + list_query(fields, criteria, item_query, assigns) |> assigns.repo.all() end @@ -92,10 +93,11 @@ defmodule Backpex.Adapters.Ecto do Returns the number of items matching the given criteria. """ @impl Backpex.Adapter - def count(fields, assigns, config, criteria \\ []) do + def count(fields, criteria, assigns, live_resource) do + config = live_resource.config(:adapter_config) item_query = prepare_item_query(config, assigns) - list_query(assigns, item_query, fields, criteria) + list_query(fields, criteria, item_query, assigns) |> exclude(:preload) |> subquery() |> config[:repo].aggregate(:count) @@ -106,7 +108,7 @@ defmodule Backpex.Adapters.Ecto do TODO: Should be private. """ - def list_query(assigns, item_query, fields, criteria \\ []) do + def list_query(fields, criteria, item_query, assigns) do %{schema: schema, full_text_search: full_text_search} = assigns associations = associations(fields, schema) diff --git a/lib/backpex/live_resource.ex b/lib/backpex/live_resource.ex index eddd4276..c41c3eef 100644 --- a/lib/backpex/live_resource.ex +++ b/lib/backpex/live_resource.ex @@ -548,14 +548,13 @@ defmodule Backpex.LiveResource do metrics = socket.assigns.live_resource.metrics() |> Enum.map(fn {key, metric} -> - query = - EctoAdapter.list_query( - assigns, - &socket.assigns.live_resource.item_query(&1, live_action, assigns), - fields, - search: search_options(query_options, fields, schema), - filters: filter_options(query_options, filters) - ) + criteria = [ + search: search_options(query_options, fields, schema), + filters: filter_options(query_options, filters) + ] + + item_query = &socket.assigns.live_resource.item_query(&1, live_action, assigns) + query = EctoAdapter.list_query(fields, criteria, item_query, assigns) case Backpex.Metric.metrics_visible?(metric_visibility, live_resource) do true -> diff --git a/lib/backpex/resource.ex b/lib/backpex/resource.ex index baf55255..a7607e5f 100644 --- a/lib/backpex/resource.ex +++ b/lib/backpex/resource.ex @@ -21,9 +21,8 @@ defmodule Backpex.Resource do """ def list(fields, assigns, live_resource, criteria \\ []) do adapter = live_resource.config(:adapter) - adapter_config = live_resource.config(:adapter_config) - adapter.list(fields, assigns, adapter_config, criteria) + adapter.list(fields, criteria, assigns, live_resource) end @doc """ @@ -32,9 +31,8 @@ defmodule Backpex.Resource do """ def count(fields, assigns, live_resource, criteria \\ []) do adapter = live_resource.config(:adapter) - adapter_config = live_resource.config(:adapter_config) - adapter.count(fields, assigns, adapter_config, criteria) + adapter.count(fields, criteria, assigns, live_resource) end @doc """ From bd4858365c2400fb1c87db82c52c1489a2c5d543 Mon Sep 17 00:00:00 2001 From: Phil-Bastian Berndt Date: Fri, 17 Jan 2025 14:06:17 +0100 Subject: [PATCH 08/23] further simplify list and count --- lib/backpex/adapter.ex | 4 ++-- lib/backpex/adapters/ash.ex | 4 ++-- lib/backpex/adapters/ecto.ex | 6 ++++-- lib/backpex/live_resource.ex | 8 +++----- lib/backpex/resource.ex | 8 ++++---- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/backpex/adapter.ex b/lib/backpex/adapter.ex index 544c0af6..be0a2e58 100644 --- a/lib/backpex/adapter.ex +++ b/lib/backpex/adapter.ex @@ -32,13 +32,13 @@ defmodule Backpex.Adapter do @doc """ Returns a list of items by given criteria. """ - @callback list(term(), term(), term(), term()) :: term() + @callback list(keyword(), map(), module()) :: list() @doc """ Gets the total count of the current live_resource. Possibly being constrained the item query and the search- and filter options. """ - @callback count(term(), term(), term(), term()) :: term() + @callback count(keyword(), map(), module()) :: integer() @doc """ Inserts given item. diff --git a/lib/backpex/adapters/ash.ex b/lib/backpex/adapters/ash.ex index 2f90f508..eaed139a 100644 --- a/lib/backpex/adapters/ash.ex +++ b/lib/backpex/adapters/ash.ex @@ -42,7 +42,7 @@ if Code.ensure_loaded?(Ash) do Returns a list of items by given criteria. """ @impl Backpex.Adapter - def list(_fields, _criteria, _assigns, live_resource) do + def list(_criteria, _assigns, live_resource) do config = live_resource.config(:adapter_config) config[:resource] @@ -54,7 +54,7 @@ if Code.ensure_loaded?(Ash) do Returns the number of items matching the given criteria. """ @impl Backpex.Adapter - def count(_fields, _criteria, _assigns, live_resource) do + def count(_criteria, _assigns, live_resource) do config = live_resource.config(:adapter_config) config[:resource] diff --git a/lib/backpex/adapters/ecto.ex b/lib/backpex/adapters/ecto.ex index 4c20b6a6..8120740e 100644 --- a/lib/backpex/adapters/ecto.ex +++ b/lib/backpex/adapters/ecto.ex @@ -81,8 +81,9 @@ defmodule Backpex.Adapters.Ecto do Returns a list of items by given criteria. """ @impl Backpex.Adapter - def list(fields, criteria, assigns, live_resource) do + def list(criteria, assigns, live_resource) do config = live_resource.config(:adapter_config) + fields = live_resource.validated_fields() item_query = prepare_item_query(config, assigns) list_query(fields, criteria, item_query, assigns) @@ -93,8 +94,9 @@ defmodule Backpex.Adapters.Ecto do Returns the number of items matching the given criteria. """ @impl Backpex.Adapter - def count(fields, criteria, assigns, live_resource) do + def count(criteria, assigns, live_resource) do config = live_resource.config(:adapter_config) + fields = live_resource.validated_fields() item_query = prepare_item_query(config, assigns) list_query(fields, criteria, item_query, assigns) diff --git a/lib/backpex/live_resource.ex b/lib/backpex/live_resource.ex index c41c3eef..6600227f 100644 --- a/lib/backpex/live_resource.ex +++ b/lib/backpex/live_resource.ex @@ -521,10 +521,8 @@ defmodule Backpex.LiveResource do end def assign_items(socket) do - %{live_resource: live_resource, fields: fields} = socket.assigns - criteria = build_criteria(socket.assigns) - items = Resource.list(fields, socket.assigns, live_resource, criteria) + items = Resource.list(criteria, socket.assigns, socket.assigns.live_resource) assign(socket, :items, items) end @@ -746,7 +744,7 @@ defmodule Backpex.LiveResource do filters: filter_options(valid_filter_params, filters) ] - item_count = Resource.count(fields, socket.assigns, live_resource, count_criteria) + item_count = Resource.count(count_criteria, socket.assigns, live_resource) per_page = params @@ -1142,7 +1140,7 @@ defmodule Backpex.LiveResource do filters: filter_options(valid_filter_params, filters) ] - item_count = Resource.count(fields, socket.assigns, live_resource, count_criteria) + item_count = Resource.count(count_criteria, socket.assigns, live_resource) %{page: page, per_page: per_page} = query_options total_pages = calculate_total_pages(item_count, per_page) new_query_options = Map.put(query_options, :page, validate_page(page, total_pages)) diff --git a/lib/backpex/resource.ex b/lib/backpex/resource.ex index a7607e5f..ed9360d4 100644 --- a/lib/backpex/resource.ex +++ b/lib/backpex/resource.ex @@ -19,20 +19,20 @@ defmodule Backpex.Resource do search: {"hello", [:title, :description]} ] """ - def list(fields, assigns, live_resource, criteria \\ []) do + def list(criteria, assigns, live_resource) do adapter = live_resource.config(:adapter) - adapter.list(fields, criteria, assigns, live_resource) + adapter.list(criteria, assigns, live_resource) end @doc """ Gets the total count of the current live_resource. Possibly being constrained the item query and the search- and filter options. """ - def count(fields, assigns, live_resource, criteria \\ []) do + def count(criteria, assigns, live_resource) do adapter = live_resource.config(:adapter) - adapter.count(fields, criteria, assigns, live_resource) + adapter.count(criteria, assigns, live_resource) end @doc """ From d134a384712c74f73638325446b3629b64d389f8 Mon Sep 17 00:00:00 2001 From: Phil-Bastian Berndt Date: Fri, 17 Jan 2025 14:09:52 +0100 Subject: [PATCH 09/23] remove fields param from insert --- lib/backpex/live_components/form_component.ex | 4 ++-- lib/backpex/resource.ex | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/backpex/live_components/form_component.ex b/lib/backpex/live_components/form_component.ex index e57cce19..f5ab6d5e 100644 --- a/lib/backpex/live_components/form_component.ex +++ b/lib/backpex/live_components/form_component.ex @@ -210,7 +210,7 @@ defmodule Backpex.FormComponent do defp handle_save(socket, key, params, save_type \\ "save") defp handle_save(socket, :new, params, save_type) do - %{assigns: %{live_resource: live_resource, fields: fields, item: item} = assigns} = socket + %{assigns: %{live_resource: live_resource, item: item} = assigns} = socket opts = [ assocs: Map.get(assigns, :assocs, []), @@ -222,7 +222,7 @@ defmodule Backpex.FormComponent do end ] - case Resource.insert(item, params, fields, socket.assigns, live_resource, opts) do + case Resource.insert(item, params, socket.assigns, live_resource, opts) do {:ok, item} -> return_to = return_to_path(save_type, live_resource, socket, socket.assigns, item, :new) diff --git a/lib/backpex/resource.ex b/lib/backpex/resource.ex index ed9360d4..a092fee1 100644 --- a/lib/backpex/resource.ex +++ b/lib/backpex/resource.ex @@ -93,12 +93,13 @@ defmodule Backpex.Resource do * `attrs` (map): A map of parameters that will be passed to the `changeset_function`. * TODO: docs """ - def insert(item, attrs, fields, assigns, live_resource, opts) do + def insert(item, attrs, assigns, live_resource, opts) do {after_save_fun, opts} = Keyword.pop(opts, :after_save_fun, &{:ok, &1}) adapter = live_resource.config(:adapter) adapter_config = live_resource.config(:adapter_config) pubsub = live_resource.config(:pubsub) + fields = live_resource.validated_fields() item |> change(attrs, fields, assigns, live_resource, Keyword.put(opts, :action, :insert)) From 127ee030b857302f970c821dd49343add0e0b28c Mon Sep 17 00:00:00 2001 From: Phil-Bastian Berndt Date: Fri, 17 Jan 2025 14:16:39 +0100 Subject: [PATCH 10/23] standardize insert and update --- lib/backpex/adapter.ex | 4 ++-- lib/backpex/adapters/ash.ex | 4 ++-- lib/backpex/adapters/ecto.ex | 8 ++++++-- lib/backpex/resource.ex | 6 ++---- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/lib/backpex/adapter.ex b/lib/backpex/adapter.ex index be0a2e58..dd4e0b0d 100644 --- a/lib/backpex/adapter.ex +++ b/lib/backpex/adapter.ex @@ -43,12 +43,12 @@ defmodule Backpex.Adapter do @doc """ Inserts given item. """ - @callback insert(term(), term()) :: term() + @callback insert(struct(), module()) :: term() @doc """ Updates given item. """ - @callback update(term(), term()) :: term() + @callback update(struct(), module()) :: term() @doc """ Updates given items. diff --git a/lib/backpex/adapters/ash.ex b/lib/backpex/adapters/ash.ex index eaed139a..56e22ca7 100644 --- a/lib/backpex/adapters/ash.ex +++ b/lib/backpex/adapters/ash.ex @@ -84,7 +84,7 @@ if Code.ensure_loaded?(Ash) do Inserts given item. """ @impl Backpex.Adapter - def insert(_item, _config) do + def insert(_item, _live_resource) do raise "not implemented yet" end @@ -92,7 +92,7 @@ if Code.ensure_loaded?(Ash) do Updates given item. """ @impl Backpex.Adapter - def update(_item, _config) do + def update(_item, _live_resource) do raise "not implemented yet" end diff --git a/lib/backpex/adapters/ecto.ex b/lib/backpex/adapters/ecto.ex index 8120740e..ae0d544a 100644 --- a/lib/backpex/adapters/ecto.ex +++ b/lib/backpex/adapters/ecto.ex @@ -254,7 +254,9 @@ defmodule Backpex.Adapters.Ecto do Inserts given item. """ @impl Backpex.Adapter - def insert(item, config) do + def insert(item, live_resource) do + config = live_resource.config(:adapter_config) + item |> config[:repo].insert() end @@ -263,7 +265,9 @@ defmodule Backpex.Adapters.Ecto do Updates given item. """ @impl Backpex.Adapter - def update(item, config) do + def update(item, live_resource) do + config = live_resource.config(:adapter_config) + item |> config[:repo].update() end diff --git a/lib/backpex/resource.ex b/lib/backpex/resource.ex index a092fee1..6d8a22f8 100644 --- a/lib/backpex/resource.ex +++ b/lib/backpex/resource.ex @@ -97,13 +97,12 @@ defmodule Backpex.Resource do {after_save_fun, opts} = Keyword.pop(opts, :after_save_fun, &{:ok, &1}) adapter = live_resource.config(:adapter) - adapter_config = live_resource.config(:adapter_config) pubsub = live_resource.config(:pubsub) fields = live_resource.validated_fields() item |> change(attrs, fields, assigns, live_resource, Keyword.put(opts, :action, :insert)) - |> adapter.insert(adapter_config) + |> adapter.insert(live_resource) |> after_save(after_save_fun) |> broadcast("created", pubsub) end @@ -121,12 +120,11 @@ defmodule Backpex.Resource do {after_save_fun, opts} = Keyword.pop(opts, :after_save_fun, &{:ok, &1}) adapter = live_resource.config(:adapter) - adapter_config = live_resource.config(:adapter_config) pubsub = live_resource.config(:pubsub) item |> change(attrs, fields, assigns, live_resource, Keyword.put(opts, :action, :update)) - |> adapter.update(adapter_config) + |> adapter.update(live_resource) |> after_save(after_save_fun) |> broadcast("updated", pubsub) end From de8347a5770ebceb6f2a26a5d2422e2d67a4c2d9 Mon Sep 17 00:00:00 2001 From: Phil-Bastian Berndt Date: Fri, 17 Jan 2025 14:24:17 +0100 Subject: [PATCH 11/23] return result tuple on list and count --- lib/backpex/adapter.ex | 4 ++-- lib/backpex/adapters/ash.ex | 2 -- lib/backpex/adapters/ecto.ex | 2 ++ lib/backpex/live_resource.ex | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/backpex/adapter.ex b/lib/backpex/adapter.ex index dd4e0b0d..fe6f1a87 100644 --- a/lib/backpex/adapter.ex +++ b/lib/backpex/adapter.ex @@ -32,13 +32,13 @@ defmodule Backpex.Adapter do @doc """ Returns a list of items by given criteria. """ - @callback list(keyword(), map(), module()) :: list() + @callback list(keyword(), map(), module()) :: {:ok, list()} @doc """ Gets the total count of the current live_resource. Possibly being constrained the item query and the search- and filter options. """ - @callback count(keyword(), map(), module()) :: integer() + @callback count(keyword(), map(), module()) :: {:ok, integer()} @doc """ Inserts given item. diff --git a/lib/backpex/adapters/ash.ex b/lib/backpex/adapters/ash.ex index 56e22ca7..bdfcf7b7 100644 --- a/lib/backpex/adapters/ash.ex +++ b/lib/backpex/adapters/ash.ex @@ -47,7 +47,6 @@ if Code.ensure_loaded?(Ash) do config[:resource] |> Ash.read() - |> then(fn {:ok, results} -> results end) end @doc """ @@ -59,7 +58,6 @@ if Code.ensure_loaded?(Ash) do config[:resource] |> Ash.count() - |> then(fn {:ok, count} -> count end) end @doc """ diff --git a/lib/backpex/adapters/ecto.ex b/lib/backpex/adapters/ecto.ex index ae0d544a..31c37199 100644 --- a/lib/backpex/adapters/ecto.ex +++ b/lib/backpex/adapters/ecto.ex @@ -88,6 +88,7 @@ defmodule Backpex.Adapters.Ecto do list_query(fields, criteria, item_query, assigns) |> assigns.repo.all() + |> then(fn items -> {:ok, items} end) end @doc """ @@ -103,6 +104,7 @@ defmodule Backpex.Adapters.Ecto do |> exclude(:preload) |> subquery() |> config[:repo].aggregate(:count) + |> then(fn count -> {:ok, count} end) end @doc """ diff --git a/lib/backpex/live_resource.ex b/lib/backpex/live_resource.ex index 6600227f..b5842543 100644 --- a/lib/backpex/live_resource.ex +++ b/lib/backpex/live_resource.ex @@ -522,7 +522,7 @@ defmodule Backpex.LiveResource do def assign_items(socket) do criteria = build_criteria(socket.assigns) - items = Resource.list(criteria, socket.assigns, socket.assigns.live_resource) + {:ok, items} = Resource.list(criteria, socket.assigns, socket.assigns.live_resource) assign(socket, :items, items) end @@ -744,7 +744,7 @@ defmodule Backpex.LiveResource do filters: filter_options(valid_filter_params, filters) ] - item_count = Resource.count(count_criteria, socket.assigns, live_resource) + {:ok, item_count} = Resource.count(count_criteria, socket.assigns, live_resource) per_page = params @@ -1140,7 +1140,7 @@ defmodule Backpex.LiveResource do filters: filter_options(valid_filter_params, filters) ] - item_count = Resource.count(count_criteria, socket.assigns, live_resource) + {:ok, item_count} = Resource.count(count_criteria, socket.assigns, live_resource) %{page: page, per_page: per_page} = query_options total_pages = calculate_total_pages(item_count, per_page) new_query_options = Map.put(query_options, :page, validate_page(page, total_pages)) From 0c0f9db4c4a053833b964d22404137bc472a242c Mon Sep 17 00:00:00 2001 From: Phil-Bastian Berndt Date: Fri, 17 Jan 2025 14:28:20 +0100 Subject: [PATCH 12/23] improve typespecs --- lib/backpex/adapter.ex | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/backpex/adapter.ex b/lib/backpex/adapter.ex index fe6f1a87..61663445 100644 --- a/lib/backpex/adapter.ex +++ b/lib/backpex/adapter.ex @@ -38,22 +38,22 @@ defmodule Backpex.Adapter do Gets the total count of the current live_resource. Possibly being constrained the item query and the search- and filter options. """ - @callback count(keyword(), map(), module()) :: {:ok, integer()} + @callback count(keyword(), map(), module()) :: {:ok, non_neg_integer()} @doc """ Inserts given item. """ - @callback insert(struct(), module()) :: term() + @callback insert(struct(), module()) :: {:ok, struct()} | {:error, term()} @doc """ Updates given item. """ - @callback update(struct(), module()) :: term() + @callback update(struct(), module()) :: {:ok, struct()} | {:error, term()} @doc """ Updates given items. """ - @callback update_all(term(), term(), term()) :: term() + @callback update_all(list(struct()), keyword(), module()) :: {:ok, non_neg_integer()} @doc """ Applies a change to a given item. @@ -63,5 +63,5 @@ defmodule Backpex.Adapter do @doc """ Deletes multiple items. """ - @callback delete_all(list(), term()) :: {:ok, term()} | {:error, term()} + @callback delete_all(list(struct()), module()) :: {:ok, term()} | {:error, term()} end From 1a9287caa32463b38b802f9924bec4bca5fcb839 Mon Sep 17 00:00:00 2001 From: Phil-Bastian Berndt Date: Fri, 17 Jan 2025 14:46:43 +0100 Subject: [PATCH 13/23] standardize change and update_all --- demo/lib/demo_web/item_actions/soft_delete.ex | 2 +- guides/actions/item-actions.md | 4 ++-- guides/upgrading/v0.5.md | 6 +++--- lib/backpex/adapter.ex | 2 +- lib/backpex/adapters/ash.ex | 4 ++-- lib/backpex/adapters/ecto.ex | 3 ++- lib/backpex/resource.ex | 5 +++-- 7 files changed, 14 insertions(+), 12 deletions(-) diff --git a/demo/lib/demo_web/item_actions/soft_delete.ex b/demo/lib/demo_web/item_actions/soft_delete.ex index c74c303b..ade715c9 100644 --- a/demo/lib/demo_web/item_actions/soft_delete.ex +++ b/demo/lib/demo_web/item_actions/soft_delete.ex @@ -64,7 +64,7 @@ defmodule DemoWeb.ItemActions.SoftDelete do socket = try do updates = [set: [deleted_at: datetime]] - {:ok, _items} = Backpex.Resource.update_all(items, updates, "deleted", socket.assigns.live_resource) + {:ok, _count} = Backpex.Resource.update_all(items, updates, "deleted", socket.assigns.live_resource) socket |> clear_flash() diff --git a/guides/actions/item-actions.md b/guides/actions/item-actions.md index d9a02cc5..9a017d9c 100644 --- a/guides/actions/item-actions.md +++ b/guides/actions/item-actions.md @@ -173,7 +173,7 @@ defmodule DemoWeb.ItemAction.SoftDelete do socket = try do - {:ok, _items} = + {:ok, _count_} = Backpex.Resource.update_all( socket.assigns, items, @@ -201,4 +201,4 @@ The `c:Backpex.ItemAction.handle/3` function is called when the item action is t By default an item action is triggered immediately when the user clicks on the corresponding icon in the resource table or in the show view, but an item actions also supports a confirmation dialog. To enable the confirmation dialog you need to implement the `c:Backpex.ItemAction.confirm/1` function and return a string that will be displayed in the confirmation dialog. The confirmation dialog will be displayed when the user clicks on the icon in the resource table. -You might want to use the `c:Backpex.ItemAction.cancel_label/0` (defaults to "Cancel") and `c:Backpex.ItemAction.confirm_label/0` (defaults to "Apply") functions to set the labels of the buttons in the dialog. \ No newline at end of file +You might want to use the `c:Backpex.ItemAction.cancel_label/0` (defaults to "Cancel") and `c:Backpex.ItemAction.confirm_label/0` (defaults to "Apply") functions to set the labels of the buttons in the dialog. diff --git a/guides/upgrading/v0.5.md b/guides/upgrading/v0.5.md index f44c1527..6cf01bf9 100644 --- a/guides/upgrading/v0.5.md +++ b/guides/upgrading/v0.5.md @@ -66,7 +66,7 @@ defmodule MyAppWeb.Admin.ItemActions.Delete do socket = try do - {:ok, _items} = + {:ok, _count} = Backpex.Resource.update_all( socket.assigns, items, @@ -100,7 +100,7 @@ defmodule MyAppWeb.Admin.ItemActions.Delete do socket = try do - {:ok, _items} = + {:ok, _count} = Backpex.Resource.update_all( socket.assigns, items, @@ -126,4 +126,4 @@ Note that the data is now casted. Therefore you now have atom keys instead of st ## Refactor the use of icons -We have refactored the way we use icons in Backpex. Previously, we installed [the Heroicons hex.pm package](https://hex.pm/packages/heroicons). We now require a Tailwind plugin that generates the styles for a new `Backpex.HTML.CoreComponents.icon/1` component. This is the default way of using heroicons in new Phoenix projects. We documented the new way in the [installation guide](get_started/installation.md#provide-tailwind-plugin-for-icons). \ No newline at end of file +We have refactored the way we use icons in Backpex. Previously, we installed [the Heroicons hex.pm package](https://hex.pm/packages/heroicons). We now require a Tailwind plugin that generates the styles for a new `Backpex.HTML.CoreComponents.icon/1` component. This is the default way of using heroicons in new Phoenix projects. We documented the new way in the [installation guide](get_started/installation.md#provide-tailwind-plugin-for-icons). diff --git a/lib/backpex/adapter.ex b/lib/backpex/adapter.ex index 61663445..274783dc 100644 --- a/lib/backpex/adapter.ex +++ b/lib/backpex/adapter.ex @@ -58,7 +58,7 @@ defmodule Backpex.Adapter do @doc """ Applies a change to a given item. """ - @callback change(term(), term(), term(), term(), term(), term()) :: term() + @callback change(struct(), map(), term(), list(), module(), keyword()) :: Ecto.Changeset.t() @doc """ Deletes multiple items. diff --git a/lib/backpex/adapters/ash.ex b/lib/backpex/adapters/ash.ex index bdfcf7b7..a6e663f7 100644 --- a/lib/backpex/adapters/ash.ex +++ b/lib/backpex/adapters/ash.ex @@ -98,7 +98,7 @@ if Code.ensure_loaded?(Ash) do Updates given items. """ @impl Backpex.Adapter - def update_all(_items, _updates, _config) do + def update_all(_items, _updates, _live_resource) do raise "not implemented yet" end @@ -106,7 +106,7 @@ if Code.ensure_loaded?(Ash) do Applies a change to a given item. """ @impl Backpex.Adapter - def change(_item, _attrs, _fields, _assigns, _config, _opts) do + def change(_item, _attrs, _fields, _assigns, _live_resource, _opts) do raise "not implemented yet" end end diff --git a/lib/backpex/adapters/ecto.ex b/lib/backpex/adapters/ecto.ex index 31c37199..3d44f7e9 100644 --- a/lib/backpex/adapters/ecto.ex +++ b/lib/backpex/adapters/ecto.ex @@ -291,7 +291,8 @@ defmodule Backpex.Adapters.Ecto do Applies a change to a given item. """ @impl Backpex.Adapter - def change(item, attrs, fields, assigns, config, opts) do + def change(item, attrs, fields, assigns, live_resource, opts) do + config = live_resource.config(:adapter_config) assocs = Keyword.get(opts, :assocs, []) target = Keyword.get(opts, :target, nil) action = Keyword.get(opts, :action, :validate) diff --git a/lib/backpex/resource.ex b/lib/backpex/resource.ex index 6d8a22f8..ac5f9480 100644 --- a/lib/backpex/resource.ex +++ b/lib/backpex/resource.ex @@ -162,7 +162,9 @@ defmodule Backpex.Resource do * `item`: The initial data structure to be changed. * `attrs`: A map of attributes that will be used to modify the item. These attributes are passed to the changeset function. + * `fields`: The fields for this change. * `assigns`: The assigns that will be passed to the changeset function. + * `live_resource`: The `Backpex.LiveResource` to be used. * `opts` (keyword list): A list of options for customizing the behavior of the change function. The available options are: * `assocs` (optional, default `[]`): A list of associations that should be put into the changeset. * `target` (optional, default `nil`): The target to be passed to the changeset function. @@ -170,9 +172,8 @@ defmodule Backpex.Resource do """ def change(item, attrs, fields, assigns, live_resource, opts \\ []) do adapter = live_resource.config(:adapter) - adapter_config = live_resource.config(:adapter_config) - adapter.change(item, attrs, fields, assigns, adapter_config, opts) + adapter.change(item, attrs, fields, assigns, live_resource, opts) end @doc """ From fe81d4ef7bcb1b81def5c613cd0570fd991e0f90 Mon Sep 17 00:00:00 2001 From: Phil-Bastian Berndt Date: Fri, 17 Jan 2025 17:32:30 +0100 Subject: [PATCH 14/23] remove obsolete item_query callback --- lib/backpex/live_resource.ex | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/lib/backpex/live_resource.ex b/lib/backpex/live_resource.ex index b5842543..3b6a700c 100644 --- a/lib/backpex/live_resource.ex +++ b/lib/backpex/live_resource.ex @@ -145,15 +145,6 @@ defmodule Backpex.LiveResource do """ @callback can?(assigns :: map(), action :: atom(), item :: map() | nil) :: boolean() - @doc """ - The function that can be used to inject an ecto query. The query will be used when resources are being fetched. This happens on `index`, `edit` - and `show` view. In most cases this function will be used to filter items on `index` view based on certain criteria, but it may also be used - to join other tables on `edit` or `show` view. - - The function has to return an `Ecto.Query`. It is recommended to build your `item_query` on top of the incoming query. Otherwise you will likely get binding errors. - """ - @callback item_query(query :: Ecto.Query.t(), live_action :: atom(), assigns :: map()) :: Ecto.Query.t() - @doc """ The function that can be used to add content to certain positions on Backpex views. It may also be used to overwrite content. @@ -328,9 +319,6 @@ defmodule Backpex.LiveResource do @impl Backpex.LiveResource def search_placeholder, do: Backpex.translate("Search") - @impl Backpex.LiveResource - def item_query(query, _live_action, _assigns), do: query - @impl Backpex.LiveResource def on_item_created(socket, _item), do: socket @@ -533,7 +521,6 @@ defmodule Backpex.LiveResource do %{ repo: repo, schema: schema, - live_action: live_action, live_resource: live_resource, fields: fields, query_options: query_options, @@ -551,8 +538,7 @@ defmodule Backpex.LiveResource do filters: filter_options(query_options, filters) ] - item_query = &socket.assigns.live_resource.item_query(&1, live_action, assigns) - query = EctoAdapter.list_query(fields, criteria, item_query, assigns) + query = EctoAdapter.list_query(fields, criteria, & &1, assigns) case Backpex.Metric.metrics_visible?(metric_visibility, live_resource) do true -> From 57310acebfac91b9027450d97642fa50e92cea29 Mon Sep 17 00:00:00 2001 From: Phil-Bastian Berndt Date: Fri, 17 Jan 2025 17:36:11 +0100 Subject: [PATCH 15/23] simplify list_query --- lib/backpex/adapters/ecto.ex | 15 ++++++--------- lib/backpex/live_resource.ex | 2 +- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/lib/backpex/adapters/ecto.ex b/lib/backpex/adapters/ecto.ex index 3d44f7e9..12ac727c 100644 --- a/lib/backpex/adapters/ecto.ex +++ b/lib/backpex/adapters/ecto.ex @@ -82,11 +82,7 @@ defmodule Backpex.Adapters.Ecto do """ @impl Backpex.Adapter def list(criteria, assigns, live_resource) do - config = live_resource.config(:adapter_config) - fields = live_resource.validated_fields() - item_query = prepare_item_query(config, assigns) - - list_query(fields, criteria, item_query, assigns) + list_query(criteria, assigns, live_resource) |> assigns.repo.all() |> then(fn items -> {:ok, items} end) end @@ -97,10 +93,8 @@ defmodule Backpex.Adapters.Ecto do @impl Backpex.Adapter def count(criteria, assigns, live_resource) do config = live_resource.config(:adapter_config) - fields = live_resource.validated_fields() - item_query = prepare_item_query(config, assigns) - list_query(fields, criteria, item_query, assigns) + list_query(criteria, assigns, live_resource) |> exclude(:preload) |> subquery() |> config[:repo].aggregate(:count) @@ -112,8 +106,11 @@ defmodule Backpex.Adapters.Ecto do TODO: Should be private. """ - def list_query(fields, criteria, item_query, assigns) do + def list_query(criteria, assigns, live_resource) do %{schema: schema, full_text_search: full_text_search} = assigns + config = live_resource.config(:adapter_config) + item_query = prepare_item_query(config, assigns) + fields = live_resource.validated_fields() associations = associations(fields, schema) schema diff --git a/lib/backpex/live_resource.ex b/lib/backpex/live_resource.ex index 3b6a700c..937138a8 100644 --- a/lib/backpex/live_resource.ex +++ b/lib/backpex/live_resource.ex @@ -538,7 +538,7 @@ defmodule Backpex.LiveResource do filters: filter_options(query_options, filters) ] - query = EctoAdapter.list_query(fields, criteria, & &1, assigns) + query = EctoAdapter.list_query(criteria, assigns, live_resource) case Backpex.Metric.metrics_visible?(metric_visibility, live_resource) do true -> From af8f135ab5a5b58245691a07413a066cbca66468 Mon Sep 17 00:00:00 2001 From: Phil-Bastian Berndt Date: Fri, 17 Jan 2025 17:40:34 +0100 Subject: [PATCH 16/23] simplify record_query --- lib/backpex/adapters/ecto.ex | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/backpex/adapters/ecto.ex b/lib/backpex/adapters/ecto.ex index 12ac727c..c5127aad 100644 --- a/lib/backpex/adapters/ecto.ex +++ b/lib/backpex/adapters/ecto.ex @@ -70,9 +70,8 @@ defmodule Backpex.Adapters.Ecto do @impl Backpex.Adapter def get(primary_value, assigns, live_resource) do config = live_resource.config(:adapter_config) - item_query = prepare_item_query(config, assigns) - record_query(primary_value, config[:schema], item_query, live_resource) + record_query(primary_value, assigns, live_resource) |> config[:repo].one() |> then(fn result -> {:ok, result} end) end @@ -345,19 +344,22 @@ defmodule Backpex.Adapters.Ecto do &query_fun.(&1, assigns.live_action, assigns) end - defp record_query(id, schema, item_query, live_resource) do + defp record_query(primary_value, assigns, live_resource) do + config = live_resource.config(:adapter_config) + item_query = prepare_item_query(config, assigns) + fields = live_resource.validated_fields() - schema_name = name_by_schema(schema) + schema_name = name_by_schema(config[:schema]) primary_key = live_resource.config(:primary_key) - primary_type = schema.__schema__(:type, primary_key) - associations = associations(fields, schema) + primary_type = config[:schema].__schema__(:type, primary_key) + associations = associations(fields, config[:schema]) - from(item in schema, as: ^schema_name, distinct: field(item, ^primary_key)) + from(item in config[:schema], as: ^schema_name, distinct: field(item, ^primary_key)) |> item_query.() |> maybe_join(associations) |> maybe_preload(associations, fields) |> maybe_merge_dynamic_fields(fields) - |> where_id(schema_name, primary_key, primary_type, id) + |> where_id(schema_name, primary_key, primary_type, primary_value) end defp where_id(query, schema_name, id_field, :id, id) do From 34e7d5f3002f69bc19875451effd1b00fa7a6465 Mon Sep 17 00:00:00 2001 From: Florian Arens <60519307+Flo0807@users.noreply.github.com> Date: Fri, 24 Jan 2025 09:40:26 +0100 Subject: [PATCH 17/23] Update upgrade guides --- guides/upgrading/v0.10.md | 12 ++++++++++++ guides/upgrading/v0.11.md | 12 ++++++++++++ guides/upgrading/v0.3.md | 2 +- guides/upgrading/v0.5.md | 12 ++++++++++++ guides/upgrading/v0.6.md | 14 +++++++++++++- guides/upgrading/v0.7.md | 12 ++++++++++++ 6 files changed, 62 insertions(+), 2 deletions(-) diff --git a/guides/upgrading/v0.10.md b/guides/upgrading/v0.10.md index ec0b186a..f85811a2 100644 --- a/guides/upgrading/v0.10.md +++ b/guides/upgrading/v0.10.md @@ -1,5 +1,17 @@ # Upgrading to v0.10 +## Bump Your Deps + +Update Backpex to the latest version: + +```elixir + defp deps do + [ + {:backpex, "~> 0.10.0"} + ] + end +``` + ## LiveView 1.0 See [phoenix_live_view changelog](https://github.com/phoenixframework/phoenix_live_view/blob/main/CHANGELOG.md) for info on how to upgrade to `1.0`. diff --git a/guides/upgrading/v0.11.md b/guides/upgrading/v0.11.md index 032bfa65..3ec41639 100644 --- a/guides/upgrading/v0.11.md +++ b/guides/upgrading/v0.11.md @@ -1,5 +1,17 @@ # Upgrading to v0.11 +## Bump Your Deps + +Update Backpex to the latest version: + +```elixir + defp deps do + [ + {:backpex, "~> 0.11.0"} + ] + end +``` + ## Parameter changes in core modules In case you are using `Backpex.Resource` or one of the `Backpex.Adapter` modules (`Backpex.Adapters.Ecto` or diff --git a/guides/upgrading/v0.3.md b/guides/upgrading/v0.3.md index 4d4c0a65..ef44eb6c 100644 --- a/guides/upgrading/v0.3.md +++ b/guides/upgrading/v0.3.md @@ -7,7 +7,7 @@ Update Backpex to the latest version: ```elixir defp deps do [ - {:backpex, "~> 0.3.1"} + {:backpex, "~> 0.3.0"} ] end ``` diff --git a/guides/upgrading/v0.5.md b/guides/upgrading/v0.5.md index 6cf01bf9..0e1a2435 100644 --- a/guides/upgrading/v0.5.md +++ b/guides/upgrading/v0.5.md @@ -1,5 +1,17 @@ # Upgrading to v0.5 +## Bump Your Deps + +Update Backpex to the latest version: + +```elixir + defp deps do + [ + {:backpex, "~> 0.5.0"} + ] + end +``` + ## Uploads: Item in `consume_upload/4` now contains changes Previously, we passed the item without its changes to the `consume_upload/4` callback function. With 0.5, we now pass the persisted item (with its changes) to the function. diff --git a/guides/upgrading/v0.6.md b/guides/upgrading/v0.6.md index b37022d2..ce0ea25b 100644 --- a/guides/upgrading/v0.6.md +++ b/guides/upgrading/v0.6.md @@ -1,5 +1,17 @@ # Upgrading to v0.6 -# Change `Backpex.Fields.ManyToMany` to `Backpex.Fields.HasMany` +## Bump Your Deps + +Update Backpex to the latest version: + +```elixir + defp deps do + [ + {:backpex, "~> 0.6.0"} + ] + end +``` + +## Change `Backpex.Fields.ManyToMany` to `Backpex.Fields.HasMany` With version 0.6, we have combined the `Backpex.Fields.ManyToMany` and `Backpex.Fields.HasMany` field. The functionality of the fields is now combined in the `Backpex.Fields.HasMany` field. The API of the field has not changed, so you can simply replace `Backpex.Fields.ManyToMany` with `Backpex.Fields.HasMany` in your resource configuration. \ No newline at end of file diff --git a/guides/upgrading/v0.7.md b/guides/upgrading/v0.7.md index 820c4fd7..a3085935 100644 --- a/guides/upgrading/v0.7.md +++ b/guides/upgrading/v0.7.md @@ -1,5 +1,17 @@ # Upgrading to v0.7 +## Bump Your Deps + +Update Backpex to the latest version: + +```elixir + defp deps do + [ + {:backpex, "~> 0.7.0"} + ] + end +``` + ## Update calls to [`Backpex.Field.handle_index_editable/2`](Backpex.Field.html#handle_index_editable/3) We have updated the arity and syntax of [`Backpex.Field.handle_index_editable/2`](Backpex.Field.html#handle_index_editable/3). It is now [`Backpex.Field.handle_index_editable/3`](Backpex.Field.html#handle_index_editable/3) and accepts the `socket`, the `value` and the `change`. We now need the value to update the form accordingly. From f2bdf4d6eca3e7f807dcf9f3af1f935150827b16 Mon Sep 17 00:00:00 2001 From: Florian Arens <60519307+Flo0807@users.noreply.github.com> Date: Fri, 24 Jan 2025 09:50:28 +0100 Subject: [PATCH 18/23] Fix warnings in docs --- guides/actions/item-actions.md | 2 +- guides/upgrading/v0.7.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/guides/actions/item-actions.md b/guides/actions/item-actions.md index 9a017d9c..dca42695 100644 --- a/guides/actions/item-actions.md +++ b/guides/actions/item-actions.md @@ -201,4 +201,4 @@ The `c:Backpex.ItemAction.handle/3` function is called when the item action is t By default an item action is triggered immediately when the user clicks on the corresponding icon in the resource table or in the show view, but an item actions also supports a confirmation dialog. To enable the confirmation dialog you need to implement the `c:Backpex.ItemAction.confirm/1` function and return a string that will be displayed in the confirmation dialog. The confirmation dialog will be displayed when the user clicks on the icon in the resource table. -You might want to use the `c:Backpex.ItemAction.cancel_label/0` (defaults to "Cancel") and `c:Backpex.ItemAction.confirm_label/0` (defaults to "Apply") functions to set the labels of the buttons in the dialog. +You might want to use the `c:Backpex.ItemAction.cancel_label/1` (defaults to "Cancel") and `c:Backpex.ItemAction.confirm_label/1` (defaults to "Apply") functions to set the labels of the buttons in the dialog. diff --git a/guides/upgrading/v0.7.md b/guides/upgrading/v0.7.md index a3085935..dc7df0cb 100644 --- a/guides/upgrading/v0.7.md +++ b/guides/upgrading/v0.7.md @@ -40,7 +40,7 @@ We have updated certain functions in `Backpex.Resource`. The following functions are affected: - `Backpex.Resource.update/6` (`update/5` before) -- `Backpex.Resource.insert/6` (`insert/5` before) +- [`Backpex.Resource.insert/6`]() (`insert/5` before) - [`Backpex.Resource.change/7`]() - [`Backpex.Resource.put_assocs/2`]() (has been removed) From 47c319d4408e876b9be747229d02779aa08283eb Mon Sep 17 00:00:00 2001 From: Florian Arens <60519307+Flo0807@users.noreply.github.com> Date: Fri, 24 Jan 2025 09:50:39 +0100 Subject: [PATCH 19/23] Update v0.8 upgrade guide --- guides/upgrading/v0.8.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/guides/upgrading/v0.8.md b/guides/upgrading/v0.8.md index dca5a592..5076827b 100644 --- a/guides/upgrading/v0.8.md +++ b/guides/upgrading/v0.8.md @@ -57,6 +57,45 @@ You now have to provide a Keyword list with the `name`, `topic` and `event_prefi In addition, all options of the LiveResource and the corresponding adapters are now validated at compile time. +### Refactor item query + +With the release of the adapter pattern, the `item_query/3` function has to be configured in the adapter config. + +If you had an `item_query/3` configuration like this: + +```elixir +# in your resource configuration file (live resource) +use Backpex.LiveResource, + # ...options + + @impl Backpex.LiveResource + def item_query(query, :index, _assigns) do + query + |> where([post], post.published) + end +``` + +change it to an adapter config: + +```elixir +# in your resource configuration file (live resource) +use Backpex.LiveResource, + # ...other options + adapter_config: [ + # ...other adapter options + item_query: &__MODULE__.item_query/3 + ] + + def item_query(query, :index, _assigns) do + query + |> where([post], post.published) + end +``` + +See [Item Query documentation](../live_resource/item-query.md) for more information. + +> Note that the `item_query/3` function is only used in `Backpex.Adapters.Ecto`. + ### Changed `Backpex.Resource` parameters If you are not using this module directly in your code, you can safely ignore this section. From 13c56031f3576881b5e575cf861a28b7aafdd7b0 Mon Sep 17 00:00:00 2001 From: Florian Arens <60519307+Flo0807@users.noreply.github.com> Date: Fri, 24 Jan 2025 09:59:06 +0100 Subject: [PATCH 20/23] Add fallback item_query for user live resource --- demo/lib/demo_web/live/user_live.ex | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/demo/lib/demo_web/live/user_live.ex b/demo/lib/demo_web/live/user_live.ex index 0f8f7190..21289b8b 100644 --- a/demo/lib/demo_web/live/user_live.ex +++ b/demo/lib/demo_web/live/user_live.ex @@ -32,6 +32,10 @@ defmodule DemoWeb.UserLive do where: is_nil(u.deleted_at) end + def item_query(query, _live_action, _assigns) do + query + end + def init_order(_assigns) do %{by: :username, direction: :asc} end From b824bd07d3d54181cdb9281de09c648a5a05f565 Mon Sep 17 00:00:00 2001 From: Florian Arens <60519307+Flo0807@users.noreply.github.com> Date: Fri, 24 Jan 2025 09:59:14 +0100 Subject: [PATCH 21/23] Update item query guide --- guides/live_resource/item-query.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/guides/live_resource/item-query.md b/guides/live_resource/item-query.md index 2cc9acd4..df4c5e3e 100644 --- a/guides/live_resource/item-query.md +++ b/guides/live_resource/item-query.md @@ -25,10 +25,16 @@ use Backpex.LiveResource, query |> where([post], post.published) end + + def item_query(query, _live_action, _assigns) do + query + end ``` The example above will filter all posts by a published boolean on `index` view. We also made use of the named binding. It's always the name of the provided schema in `snake_case`. It is recommended to build your `item_query` on top of the incoming query. Otherwise you will likely get binding errors. +Make sure to always cover all possible cases or add a fallback `item_query/3` function that just returns the query. + > #### Important {: .info} > > Note that it is not possible to use an anonymous function for `item_query` configuration. You must refer to a public function defined within a module. From b798243ddbf13bcdf4018f8b61b308f7cf5db093 Mon Sep 17 00:00:00 2001 From: Florian Arens <60519307+Flo0807@users.noreply.github.com> Date: Fri, 24 Jan 2025 09:59:24 +0100 Subject: [PATCH 22/23] Update v0.8 upgrade guide --- guides/upgrading/v0.8.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/guides/upgrading/v0.8.md b/guides/upgrading/v0.8.md index 5076827b..64408863 100644 --- a/guides/upgrading/v0.8.md +++ b/guides/upgrading/v0.8.md @@ -90,6 +90,10 @@ use Backpex.LiveResource, query |> where([post], post.published) end + + def item_query(query, _live_action_, _assigns) do + query + end ``` See [Item Query documentation](../live_resource/item-query.md) for more information. From facf5c570ad281be1f5e7f2eb6130c67187f19f1 Mon Sep 17 00:00:00 2001 From: Florian Arens <60519307+Flo0807@users.noreply.github.com> Date: Fri, 24 Jan 2025 10:09:55 +0100 Subject: [PATCH 23/23] Update upgrade guide --- guides/upgrading/v0.11.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/guides/upgrading/v0.11.md b/guides/upgrading/v0.11.md index 3ec41639..f533f9b0 100644 --- a/guides/upgrading/v0.11.md +++ b/guides/upgrading/v0.11.md @@ -17,3 +17,31 @@ Update Backpex to the latest version: In case you are using `Backpex.Resource` or one of the `Backpex.Adapter` modules (`Backpex.Adapters.Ecto` or `Backpex.Adapters.Ash`) directly check out the updated function definitions. This will also apply in case you built your own adapter. + +## Make sure to cover all cases with the `item_query/3` function + +We have removed code that ensures that a fallback item query function is always added to your LiveResource. + +Make sure to always cover all possible cases or add a fallback `item_query/3` function that just returns the query. + +For example: + +```elixir +# in your resource configuration file (live resource) +use Backpex.LiveResource, + # ...other options + adapter_config: [ + # ...other adapter options + item_query: &__MODULE__.item_query/3 + ] + + def item_query(query, :index, _assigns) do + query + |> where([post], post.published) + end + + # make sure to add this fallback function + def item_query(query, _live_action, _assigns) do + query + end +``` \ No newline at end of file