Code Monkey home page Code Monkey logo

backpex's People

Contributors

dependabot[bot] avatar flo0807 avatar gcpreston avatar guess avatar io2 avatar kianmeng avatar krns avatar makl9797 avatar mrmovl avatar pehbehbeh avatar sebastianmueller87 avatar thomasfortes avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

backpex's Issues

Hex dependency resolution failed

A clean install of phoenix version 1.7.14 and backpex 0.3.1 fails dependency checks

Because your app depends on backpex ~> 0.3.1 which depends on phoenix_html ~> 3.0, phoenix_html ~> 3.0 is required.
So, because your app depends on phoenix_html ~> 4.1, version solving failed.

Updating to backpex 0.4.0 fixes the issue but then causes problems with floki and heroicons:

Dependencies have diverged:
* floki (Hex package)
  the :only option for dependency floki

  > In mix.exs:
    {:floki, ">= 0.30.0", [env: :prod, hex: "floki", only: :test, repo: "hexpm"]}

  does not match the :only option calculated for

  > In deps/backpex/mix.exs:
    {:floki, ">= 0.30.0", [env: :prod, hex: "floki", repo: "hexpm", optional: false]}

  Remove the :only restriction from your dep
* heroicons (https://github.com/tailwindlabs/heroicons.git - v2.1.1)
  the dependency heroicons in mix.exs is overriding a child dependency:

  > In mix.exs:
    {:heroicons, [env: :prod, git: "https://github.com/tailwindlabs/heroicons.git", tag: "v2.1.1", sparse: "optimized", app: false, compile: false, depth: 1]}

  > In deps/backpex/mix.exs:
    {:heroicons, "~> 0.5.0", [env: :prod, hex: "heroicons", repo: "hexpm", optional: false]}

  Ensure they match or specify one of the above in your deps and set "override: true"
** (Mix) Can't continue due to errors on dependencies

Filters: Define presets inside the filter

To simplify reuse, it should be possible to specify the presets within the flilter definition, as these are very verbose.

Image

 issued_at: %{
        module: DateRange,
        presets: [
          %{
            label: dgettext("time_tracking", "Current Week"),
            values: fn ->
              %{
                "start" =>
                  DateTime.now!(@default_timezone)
                  |> DateTime.to_date()
                  |> Date.beginning_of_week(:monday),
                "end" =>
                  DateTime.now!(@default_timezone)
                  |> DateTime.to_date()
                  |> Date.end_of_week(:monday)
              }
            end
          },
          %{
            label: dgettext("time_tracking", "Last Week"),
            values: fn ->
              %{
                "start" =>
                  DateTime.now!(@default_timezone)
                  |> DateTime.to_date()
                  |> Date.beginning_of_week(:monday)
                  |> Date.add(-7),
                "end" =>
                  DateTime.now!(@default_timezone)
                  |> DateTime.to_date()
                  |> Date.end_of_week(:monday)
                  |> Date.add(-7)
              }
            end
          },
          %{
            label: dgettext("time_tracking", "Current Month"),
            values: fn ->
              %{
                "start" =>
                  DateTime.now!(@default_timezone)
                  |> DateTime.to_date()
                  |> Date.beginning_of_month(),
                "end" =>
                  DateTime.now!(@default_timezone)
                  |> DateTime.to_date()
                  |> Date.end_of_month()
              }
            end
          },
          %{
            label: dgettext("time_tracking", "Last Month"),
            values: fn ->
              %{
                "start" =>
                  DateTime.now!(@default_timezone)
                  |> DateTime.to_date()
                  |> Date.beginning_of_month()
                  |> Date.add(-1)
                  |> Date.beginning_of_month(),
                "end" =>
                  DateTime.now!(@default_timezone)
                  |> DateTime.to_date()
                  |> Date.beginning_of_month()
                  |> Date.add(-1)
                  |> Date.end_of_month()
              }
            end
          }
        ]
      }

Range Filter UI improvement

On the demo site, you can filter by the number of Likes a Post has. You can put in one or two numbers to be the endpoints of the range of Likes to show. But the fields don't say which is which, and if someone is unfamiliar, they may not even know why there are two fields. Fortunately, the example links for "over 100" and "1–99" fill in the correct numbers so the behavior can be discovered that way.

Suggested labels:

  • "From [______]"
    "To [______]"
  • "Between [_______]"
    "and [______]"
  • Inline the fields: "[______] to [______]"
  • "[______][_______]"

Heroicons module is not available

After updating backpex 0.5.1, I did all the required changes for 0.5.1.

However, I am still getting an error that the Heroicons module is not available.

image

Global Search

Make all resources searchable via a global search in the topbar.

Filters: Make label configurable from outside

To increase the reusability, a label should be configurable from the outside. The following filter can only be used when the label is the same:

defmodule EvuPlatformWeb.Filters.DateRange do
  @moduledoc false

  use Backpex.Filters.Range
  import EvuPlatformWeb.Gettext

  @impl Backpex.Filters.Range
  def type, do: :datetime

  @impl Backpex.Filter
  def label, do: dgettext("time_tracking", "Date")
end

Case insensitive sorting

Sorting should not be case sensitive.

Possible solutions:

  • fragment("lower(?)"): Works on text only
  • citext postgres extension: must be added by the user

CSS & JS not loading

Successfully ran the backpex into my project but it seems CSS not loading. Also, showing empty label buttons.

image

Also, it shows large icons.

image

Generic Filters

Filters should work in the same way as fields: without defining a separate module. We should provide a set of generic filter modules wich can then be configured in the LiveResource (just like fields).

This will work well with #336 together.

Invalid filter values result in internal server error

Invalid filter values should not result in a 500 internal server error.

For example, the user filter on the post resource is a multi select filter. You can add more users by repeating the filters[user][] parameter in the URL:

/posts?filters[user_id][]=<user_id>&filters[user_id][]=<user_id>

But because we expect the multi select filter values to be in this structure, the following URL will return a 500 internal server error:

/posts?filters[user_id]=<user_id>

Either the filter values should be ignored in this case or a bad request should be returned by the server.

There is also an error if the given `user_id' is not a UUID.

mix generators

Ideas

  • mix backpex.gen.gettext generates the language file
  • mix backpex.gen.resource generates a live resource

Index form: Remove dupliate IDs

I saw the following log in the developer console:

Multiple IDs detected: index_form_index_input. Ensure unique element ids.

This was certainly introduced with the index editable feature.

Update installation guide

Installation guide should be updated.

see #399 and #398

  • Mention Alpinejs in prerequisites
  • Mention prerequisites in installation guide
  • Note that@tailwindcss/forms plugin can lead to styling issues (describe how to use strategy: 'class' approach)
  • Note that background colors on body-tag should be removed
  • Adjust deps folder path in tailwind.config.js
  • Explain workaround for Heroicons plugin approach see #401
  • Note to daisyui light mode

Add configuration for create button label

The label for the create button should be configurable. This also includes the create button in the empty state.

  • Add a create_button_label function / option to live resources
  • Add guide for new feature

Reusable `field_input` component

We should make the field_input component generic so that it can be used by other projects as well as wherever we need form inputs in backpex (e.g., filter).

Field: Add custom css classes

Sometimes we need to override a select field only because of one additional class like w-36:

~H"""
    <div>
      <.form
        :let={f}
        for={%{}}
        as={:index_form}
        class="relative"
        phx-change="update-field"
        phx-submit="update-field"
        phx-target={@myself}
      >
        <%= Phoenix.HTML.Form.select(
          f,
          :index_input,
          @options,
          class: ["select w-36 select-sm", if(@valid, do: "hover:input-bordered", else: "select-error")],
          selected: @value,
          disabled: @readonly,
          id: @input_id,
          prompt: Map.get(@prompt, :prompt)
        ) %>
      </.form>
    </div>
    """

It would be helpful to pass additional classes to the fields.

LiveResource: default pubsub settings

All pubsub settings could be optional:

  • pubsub: use :pubsub_server option of the endpoint?
  • topic: derive from resource name?
  • event_prefix: derive from resource name?

Steps missing in installation guide?

Hi, I've been trying to add backpex to my project. Most things seems to work, but there is something with the styles that is not working properly. I also tried creating a fresh phoenix project (https://github.com/rakso-startkoden/backpex-test) and following in the steps, but its also not working 100% as expected.
In both cases there are no errors in consoles to give any clues as to what is wrong. Alpinejs is installed and tailwind config is updated as instructed.
Below are also some screenshots from my two attempts.

(From the fresh phoenix project)
Screenshot from 2024-06-22 14-18-46
Screenshot from 2024-06-22 14-18-36

(From my already existing project)
Screenshot from 2024-06-22 14-15-25

Thank you for a great project with lots of potential! I look forward to getting rid of my repetitive code for admin views.:)

do you need help

@Flo0807 Do you need help with the project? I see a lot PR's pending and some work required, I'm willing to help.
Also do you have a roadmap of feature you want to implement?
Cheers

Remove `phx-feedback-for`

With Phoenix LiveView 1.0 phx-feedback-for is being removed (see changelog). Adjust Backpex accordingly and use the new way of hiding errors of untouched form inputs.

  • Update field_input component
  • Remove the phx-no-feedback tailwind variant from demo project
  • Remove CSS for phx-no-feedback from demo project

Crash after creating a resource

backpex version: 0.4.0
phoenix version: 1.7.14
phoenix_live_view version: 0.20.17
elixir version: 1.17.1
otp version: 26.2.5

I followed the installation guide on a freshly generated mix phoenix project. I applied the fixes from #399 and got the app to boot but it crashes when I try to create a post

[error] ** (ArgumentError) attempting to set id attribute to 1, but setting the DOM ID to a number can lead to unpredictable behaviour. Instead consider prefixing the id with a string, such as "user-1" or similar
    (phoenix_html 4.1.1) lib/phoenix_html.ex:258: Phoenix.HTML.id_value/1
    (phoenix_html 4.1.1) lib/phoenix_html.ex:223: Phoenix.HTML.build_attrs/1
    (phoenix_html 4.1.1) lib/phoenix_html.ex:191: Phoenix.HTML.attributes_escape/1
    (backpex 0.4.0) lib/backpex/html/resource/resource_index_table.html.heex:78: anonymous fn/4 in Backpex.HTML.Resource."resource_index_table (overridable 1)"/1
    (phoenix_live_view 0.20.17) lib/phoenix_live_view/diff.ex:391: Phoenix.LiveView.Diff.traverse/7
    (phoenix_live_view 0.20.17) lib/phoenix_live_view/diff.ex:559: anonymous fn/3 in Phoenix.LiveView.Diff.traverse_comprehension/5
    (elixir 1.17.1) lib/enum.ex:1829: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3
    (elixir 1.17.1) lib/enum.ex:1829: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3
    (elixir 1.17.1) lib/enum.ex:1829: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3
    (phoenix_live_view 0.20.17) lib/phoenix_live_view/diff.ex:480: Phoenix.LiveView.Diff.traverse/7
    (phoenix_live_view 0.20.17) lib/phoenix_live_view/diff.ex:532: anonymous fn/4 in Phoenix.LiveView.Diff.traverse_dynamic/7
    (elixir 1.17.1) lib/enum.ex:2531: Enum."-reduce/3-lists^foldl/2-0-"/3
    (phoenix_live_view 0.20.17) lib/phoenix_live_view/diff.ex:389: Phoenix.LiveView.Diff.traverse/7
    (phoenix_live_view 0.20.17) lib/phoenix_live_view/diff.ex:532: anonymous fn/4 in Phoenix.LiveView.Diff.traverse_dynamic/7
    (elixir 1.17.1) lib/enum.ex:2531: Enum."-reduce/3-lists^foldl/2-0-"/3
    (phoenix_live_view 0.20.17) lib/phoenix_live_view/diff.ex:389: Phoenix.LiveView.Diff.traverse/7
    (phoenix_live_view 0.20.17) lib/phoenix_live_view/diff.ex:532: anonymous fn/4 in Phoenix.LiveView.Diff.traverse_dynamic/7
    (elixir 1.17.1) lib/enum.ex:2531: Enum."-reduce/3-lists^foldl/2-0-"/3
    (phoenix_live_view 0.20.17) lib/phoenix_live_view/diff.ex:389: Phoenix.LiveView.Diff.traverse/7
    (phoenix_live_view 0.20.17) lib/phoenix_live_view/diff.ex:532: anonymous fn/4 in Phoenix.LiveView.Diff.traverse_dynamic/7

Here's my post schema

defmodule BackpexPlayground.Blog.Post do
  use Ecto.Schema
  import Ecto.Changeset

  schema "blog_posts" do
    field :title, :string
    field :views, :integer

    timestamps(type: :utc_datetime)
  end

  @doc false
  def changeset(post, attrs) do
    post
    |> cast(attrs, [:title, :views])
    |> validate_required([:title, :views])
  end

  def update_changeset(post, attrs, _metadata \\ []) do
    changeset(post, attrs)
  end

  def create_changeset(post, attrs, _metadata \\ []) do
    changeset(post, attrs)
  end
end

and live view

defmodule BackpexPlaygroundWeb.Live.PostLive do
  use Backpex.LiveResource,
    layout: {BackpexPlaygroundWeb.Layouts, :admin},
    schema: BackpexPlayground.Blog.Post,
    repo: BackpexPlayground.Repo,
    update_changeset: &BackpexPlayground.Blog.Post.update_changeset/3,
    create_changeset: &BackpexPlayground.Blog.Post.create_changeset/3,
    pubsub: BackpexPlayground.PubSub,
    topic: "posts",
    event_prefix: "post_"

  @impl Backpex.LiveResource
  def singular_name, do: "Post"

  @impl Backpex.LiveResource
  def plural_name, do: "Posts"

  @impl Backpex.LiveResource
  def fields do
  [
    title: %{
      module: Backpex.Fields.Text,
      label: "Title"
    },
    views: %{
      module: Backpex.Fields.Number,
      label: "Views"
    }
  ]
  end
end

BadRequest when filtering with invalid UUID

This works:

https://backpex.live/admin/posts?filters[user_id][]=098f1b60-54d6-40bc-a8f9-986b2c95c1a9

This results in a bad request:

https://backpex.live/admin/posts?filters[user_id][]=INVALID

This is because we are trying to cast the value to a UUID internally.

Fix Heroicons dependency conflict

Backpex still uses the old way of installing Heroicons by relying on the Heroicons package. In newly generated Phoenix applications, this package is no longer used. Instead, the Heroicons GitHub repository is tracked, and a Tailwind plugin generates the appropriate CSS for an icon component.

This is a problem because Backpex tries to load the hex package heroicons while newly generated applications try to track the Hericons GitHub repository under that name.

We should probably rely on the new way of integrating Heroicons as well, but then the user has to provide the Tailwind plugin, since Backpex does not ship with a tailwind.config.js.

related to #399

Alias conflict in queries due to multiple BelongsTo fields with the same schema

When a LiveResource includes two BelongsTo fields referencing the same schema, an error occurs due to alias conflicts during query joins. The alias for each join is generated from the schema name of the associated field (see resource.ex, L108).

Attempting to set the same alias for the second BelongsTo field raises an Ecto.Query.CompileError with the message: "alias :<schema_name> already exists."

Remove floki

The Floki dependency is only being used for inserting the Backpex logo (see Layout.ex#L245).

Maybe we can provide a component for the logo that contains the svg. That way we could remove the dependency entirely.

The dependency causes a conflict in some Phoenix applications because the only: [:test] option is set by default in newly generated apps.

related to #399

Dashboards?

Hi, I'm using currently kaffy and consider to switch over to backpex. Is there a dashboard feature in planning?

Form error hint is only shown after second submit

  • The error message hint (next to the submit button) is only shown on the second submit.
  • However, errors for the individual fields are already there after the first click (this is correct).

Demo

error-hint.mp4

Uniform Options

Description

  • We would like to create a standardised way for options in Backpex.
  • In future, there will be three places to set all options:
    1. Module Level: Modules (Fields, Filters, Metrics, ...) have a standardised location where default options can be defined.
    2. Config Level: The defaults can be overwritten via the application config.
    3. Resource Level: The value set in the respective LiveResource has the highest priority.
  • At the same time, we can then implement a validation of the options to prevent errors during development.

Todos

  • Backpex.Field
  • Backpex.Filter
  • Backpex.Metric
  • ...
  • Stoerti.LiveResource

Concept

Module Level (package defaults)

see also nimble_options

defmodule Stoerti.Fields.Date do
  # ... 
 
  def options() do
    [
      format: [
        type: :string,
        default: "%Y-%m-%d"
      ],
      foo: [
        type: :non_neg_integer,
        required: true
      ]
    ]
  end  
end

Config Level (application config)

config :backpe, Backpex.Fields.Date,
  format: "%d.%m.%Y"

config: :backpex, Backpex.Fields.Upload,
  max_file_size: 42_000_000

Resource Level (application domain)

The familiar way:

      def fields do
        [
          %{
            module: Stoerti.Fields.Date,
            label: "Created At",
            name: :created_at,
            format: "%d.%m.%Y"
          }
        ]
      end

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.