Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

standardize and improve resource and adapter modules #667

Merged
merged 25 commits into from
Jan 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
987e1e6
remove adapter specific bang function
pehbehbeh Nov 14, 2024
451618a
Merge branch 'develop' into feature/adapter-bang
pehbehbeh Jan 17, 2025
40822a0
simplify docs
pehbehbeh Jan 17, 2025
6c8ca66
fix dockerfile casing
pehbehbeh Jan 17, 2025
84505e0
improve ash info
pehbehbeh Jan 17, 2025
0264780
remove usage of bang functions in ash adapter
pehbehbeh Jan 17, 2025
c6a623c
add upgrade guide for 0.10
pehbehbeh Jan 17, 2025
ddb5db8
change parameter order for adapter list and count
pehbehbeh Jan 17, 2025
bd48583
further simplify list and count
pehbehbeh Jan 17, 2025
d134a38
remove fields param from insert
pehbehbeh Jan 17, 2025
127ee03
standardize insert and update
pehbehbeh Jan 17, 2025
de8347a
return result tuple on list and count
pehbehbeh Jan 17, 2025
0c0f9db
improve typespecs
pehbehbeh Jan 17, 2025
1a9287c
standardize change and update_all
pehbehbeh Jan 17, 2025
fe81d4e
remove obsolete item_query callback
pehbehbeh Jan 17, 2025
57310ac
simplify list_query
pehbehbeh Jan 17, 2025
af8f135
simplify record_query
pehbehbeh Jan 17, 2025
cd27831
Merge pull request #785 from naymspace/feature/item-query-improvements
Flo0807 Jan 24, 2025
34e7d5f
Update upgrade guides
Flo0807 Jan 24, 2025
f2bdf4d
Fix warnings in docs
Flo0807 Jan 24, 2025
47c319d
Update v0.8 upgrade guide
Flo0807 Jan 24, 2025
13c5603
Add fallback item_query for user live resource
Flo0807 Jan 24, 2025
b824bd0
Update item query guide
Flo0807 Jan 24, 2025
b798243
Update v0.8 upgrade guide
Flo0807 Jan 24, 2025
facf5c5
Update upgrade guide
Flo0807 Jan 24, 2025
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
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ EXPOSE 4000
# Stage: release
########################################################################

FROM builder as release
FROM builder AS release

ENV MIX_ENV=prod

Expand Down
2 changes: 1 addition & 1 deletion demo/lib/demo_web/item_actions/soft_delete.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
4 changes: 2 additions & 2 deletions demo/lib/demo_web/live/ticket_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ defmodule DemoWeb.TicketLive do
<Backpex.HTML.CoreComponents.icon name="hero-information-circle" class="h-5 w-5" />
<p>
This resource uses the <strong>Ash adapter</strong>, which is currently in a very early alpha stage.
Currently, only <strong>index</strong> and <strong>show</strong> are functional in a very basic form.
We are working on supporting more Backpex features in the future.
Currently, only <strong>index</strong>, <strong>show</strong> and <strong>delete</strong> are functional in a
very basic form. We are working on supporting more Backpex features in the future.
</p>
</div>
"""
Expand Down
4 changes: 4 additions & 0 deletions demo/lib/demo_web/live/user_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions guides/actions/item-actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ defmodule DemoWeb.ItemAction.SoftDelete do

socket =
try do
{:ok, _items} =
{:ok, _count_} =
Backpex.Resource.update_all(
socket.assigns,
items,
Expand Down Expand Up @@ -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.
6 changes: 6 additions & 0 deletions guides/live_resource/item-query.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
17 changes: 17 additions & 0 deletions guides/upgrading/v0.10.md
Original file line number Diff line number Diff line change
@@ -0,0 +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`.
47 changes: 47 additions & 0 deletions guides/upgrading/v0.11.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# 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
`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
```
2 changes: 1 addition & 1 deletion guides/upgrading/v0.3.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Update Backpex to the latest version:
```elixir
defp deps do
[
{:backpex, "~> 0.3.1"}
{:backpex, "~> 0.3.0"}
]
end
```
Expand Down
18 changes: 15 additions & 3 deletions guides/upgrading/v0.5.md
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -66,7 +78,7 @@ defmodule MyAppWeb.Admin.ItemActions.Delete do

socket =
try do
{:ok, _items} =
{:ok, _count} =
Backpex.Resource.update_all(
socket.assigns,
items,
Expand Down Expand Up @@ -100,7 +112,7 @@ defmodule MyAppWeb.Admin.ItemActions.Delete do

socket =
try do
{:ok, _items} =
{:ok, _count} =
Backpex.Resource.update_all(
socket.assigns,
items,
Expand All @@ -126,4 +138,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).
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).
14 changes: 13 additions & 1 deletion guides/upgrading/v0.6.md
Original file line number Diff line number Diff line change
@@ -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.
14 changes: 13 additions & 1 deletion guides/upgrading/v0.7.md
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -28,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)

Expand Down
43 changes: 43 additions & 0 deletions guides/upgrading/v0.8.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,49 @@ 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

def item_query(query, _live_action_, _assigns) do
query
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.
Expand Down
23 changes: 8 additions & 15 deletions lib/backpex/adapter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,48 +27,41 @@ 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.
"""
@callback list(term(), term(), term(), term()) :: term()
@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(term(), term(), term(), term()) :: term()
@callback count(keyword(), map(), module()) :: {:ok, non_neg_integer()}

@doc """
Inserts given item.
"""
@callback insert(term(), term()) :: term()
@callback insert(struct(), module()) :: {:ok, struct()} | {:error, term()}

@doc """
Updates given item.
"""
@callback update(term(), term()) :: 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.
"""
@callback change(term(), term(), term(), term(), term(), term()) :: term()
@callback change(struct(), map(), term(), list(), module(), keyword()) :: Ecto.Changeset.t()

@doc """
Deletes multiple items.
"""
@callback delete_all(list(), term()) :: {:ok, term()} | {:error, term()}
@callback delete_all(list(struct()), module()) :: {:ok, term()} | {:error, term()}
end
Loading
Loading