Git Product home page Git Product logo

Comments (9)

woylie avatar woylie commented on June 14, 2024 1

@jesselathamdev There are a lot of things to consider here. I think we have some easy issues that we can tackle first. I'll try to find some time for the sortable tables in the next couple of days.

from flop_phoenix.

jesse-iluminai avatar jesse-iluminai commented on June 14, 2024

Hi @woylie I'm interested in using Flop. Everything looks pretty great so far but any chance you might find some time to implement the sortable view helpers for use in tables and such?

As life can very easily and understandably get in our way, what's the current status of Flop? Are you planning to put some additional effort into it? I find that a complete solution for pagination, sorting, and maybe some boilerplate for an example search form (like/unlike Ransack for Rails) is greatly missing from the Phoenix/Elixir ecosystem.

from flop_phoenix.

woylie avatar woylie commented on June 14, 2024

Hey @jesse-iluminai, thanks for your interest in the library. We're using the Flop libraries in production in two or three projects at the moment, but mostly for the pagination part (both in admin interfaces and for Relay pagination with Absinthe). I didn't have a lot of time recently to work on new features, so I'm mostly working on updates whenever new functionality is needed in our projects. A pagination component for LiveView and sortable tables will probably be the next features we'll need, but I can't give you a timeline at the moment.

from flop_phoenix.

jesse-iluminai avatar jesse-iluminai commented on June 14, 2024

Thanks for the info @woylie, much appreciated and understood. Looking forward to seeing what you come up with when you have a chance!

from flop_phoenix.

jesselathamdev avatar jesselathamdev commented on June 14, 2024

@woylie me again :)

Hey so I want to go forward with using Flop and the helpers you've been building for the Phoenix side. There are some enhancements that I'd like to see for an upcoming project and I'm happy to help out in making them happen over time.

If you don't mind I'm just going to list them here and you can decide how to carve these out to separate items etc. I'm also guessing that the use cases here are both for the UI and an API (I haven't done much digging into Relay yet so I'm not sure of what of Flop supports that directly).

From a UI/UX point of view here is my wishlist/my own to-do list:

  • Pagination: Default Page Size / Max Page Size - have you considered that for the UI that there is an optionally static "limit"? There are some UI set ups though where a user can choose how many items per page they want to see (10, 25, 50) so the current set up works well for that.
  • Pagination: In the URLs from the pagination view remove the "page_size" attribute from appearing by default - this hints to the users that they could change this (which is fair) but if we can keep the URLs less crufty that would be awesome
  • Pagination: First/Last pagination link and modifier support - in addition to what's you have already
  • Sorting: We've talked about this in the ticket here already, but do you have any thoughts on how you'd start this as I'm wanting this for an upcoming project I'll be building something to work with Flop
  • Searching: Omnibox style - unlike Rummage where a separate field exists for each filterable you wish to use I typically implement on projects a single field which typically works on an ilike basis; other types of fields like dates and select type fields I would be adding to an "Advanced" search
  • Searching: Have you had any thoughts on how to put together constructed fields like Ransack from the Ruby world? Best example would be that I have a field for first_name and last_name and want to be able to have a user search for "John He" and would like to concat those fields within the search mechanism

Anyways, let me know what you think.

from flop_phoenix.

woylie avatar woylie commented on June 14, 2024

Hey @jesselathamdev, thanks for the suggestions!

Pagination: Default Page Size / Max Page Size - have you considered that for the UI that there is an optionally static "limit"? There are some UI set ups though where a user can choose how many items per page they want to see (10, 25, 50) so the current set up works well for that.

Do you mean that you want to disable the limit/page_size parameters? We already have options to disable the ordering and filtering parameters. We could add another one to disable setting the limit via parameters. Is that what you suggest?

Pagination: In the URLs from the pagination view remove the "page_size" attribute from appearing by default - this hints to the users that they could change this (which is fair) but if we can keep the URLs less crufty that would be awesome

One way to do this would be to remove the page_size parameter if the value is the same as the default value. However, the FlopPhoenix pagination helper does not get the schema settings at the moment. An easier way to do this would probably be to add another option to the pagination function (see existing options - disable_page_size_param or something like that).

Pagination: First/Last pagination link and modifier support - in addition to what's you have already

Yes, the first and last page links are definitely missing (#12). What do you mean with "modifier support"?

Sorting: We've talked about this in the ticket here already, but do you have any thoughts on how you'd start this as I'm wanting this for an upcoming project I'll be building something to work with Flop

I made a non-sortable table helper for a project that I'd modify for sortable headers with Flop. I'll send you some details later.

Searching: Omnibox style - unlike Rummage where a separate field exists for each filterable you wish to use I typically implement on projects a single field which typically works on an ilike basis; other types of fields like dates and select type fields I would be adding to an "Advanced" search

Searching: Have you had any thoughts on how to put together constructed fields like Ransack from the Ruby world? Best example would be that I have a field for first_name and last_name and want to be able to have a user search for "John He" and would like to concat those fields within the search mechanism

The filtering feature of Flop is a bit clunky at the moment and could surely use some improvements.

Currently you always have to specify the field, value and operator, and it has to be a map, which makes the query parameters pretty verbose. It might be nicer in some cases if you could just set key/value parameters (name=rocky or filters[name]=rocky) and have Flop convert that to the Filter type behind the scenes. You should still be able to set the default operator per field, though.

Maybe we can change the type of the filter field of the Flop struct to [Flop.Filter.t()] | keyword | nil or [Flop.Filter.t() | {atom, any}] | nil.

For a simple free text search (omnibox), we could add a q or query field to Flop. We could then add a free_text_fields option to Flop.Schema. To only support this simple use case, the option value would just be a list of fields to search in.

If you need a more flexible way of searching across fields (e.g. you need one field to search in title/subtitle and another one to search in description/additional_info), the free_text_fields option could be a keyword list instead: [title_or_subtitle: [:title, :subtitle], description_or_additional_info: [:description, :additional_info]]. We wouldn't need an additional q field then. You would be able to use the simple filter format.

We could specify the default operators to be used for simple filters and constructed fields in Flop.Schema like this: default_operators: [title: :ilike_or, category: :==, title_or_subtitle: :ilike_and].

All of this is just quickly jotted down without thinking it through. Let me know what you think.

Edit: new issues for the search: woylie/flop#87 and woylie/flop#88

from flop_phoenix.

jesselathamdev avatar jesselathamdev commented on June 14, 2024

@woylie hopefully I don't make too much mess with the additional quoting here...

Do you mean that you want to disable the limit/page_size parameters? We already have options to disable the ordering and filtering parameters. We could add another one to disable setting the limit via parameters. Is that what you suggest?

I think this was two-fold. Mostly my problem with something like Rummage is that the URLs are so crufty, making copying/pasting a filtered/sorted/pagintated URL to a colleague just a mess of a string. So here I was first envisioning that in UI cases we wouldn't want to hint to a user that they can change the page size so we'd prevent the ?page_size=n query string param from appearing, and then go a step further and not make it changeable by allowing sometime to attempt to fuss with the parameter, hence simply setting an actual limit (same as per_page) in the config options. This would optionally negate the need for setting a default_limit or max_limit if all we ever wanted was to display 25 items (or less for the remainder) per page.

One way to do this would be to remove the page_size parameter if the value is the same as the default value. However, the FlopPhoenix pagination helper does not get the schema settings at the moment. An easier way to do this would probably be to add another option to the pagination function (see existing options - disable_page_size_param or something like that).

Either of these methods solves for my above elaborated comment!

Yes, the first and last page links are definitely missing (#12). What do you mean with "modifier support"?

Awesome, saw the ticket you raised! Poor wording on my part sorry. With "modifier support" I was thinking of being able to provide a way to provide an entirely custom wrapper/HTML/class support. Less of an issue if the HTML schema and provided classes allow us to do what we want to.

I made a non-sortable table helper for a project that I'd modify for sortable headers with Flop. I'll send you some details later.

Nice - will take a look when you're ready.

The filtering feature of Flop is a bit clunky at the moment and could surely use some improvements.

Yes, there's definitely a lot to digest here, especially with considerations to providing a positive DX for all of us. I think with something like Ransack for Rails there was a lot learned. I think at the end we need to allow developers to be expressive and not be locked into a particular look/feel for how they would be required to implement a search box. Boiling this down I mainly want to be able to specify my own HTML form, GETting the results from the same URL of the list route, and on the server side whitelist with the predicates on what is allowed to be passed through (and silently tossing anything not matching that pattern as to avoid throwing unnecessary 404's/and unhandled 500's back at the user.

I do like having a simple query string param like "q" or "query" for the filtering portion (like when sorting maybe an "s" or "sort" w.r.t. "s[first_name]=asc" and so on).

Not that Flop should aim to become an exact Ransack clone, but we do need something that the community can help grow over time and there are a lot of nice features there (such as being able to access/produce the underlying SQL for more advanced queries and exact control. When constructing fields, it's been important to the projects I've worked on to be able to work with equivalent fragments for SQL like lower or casting from UUID to text customer_id::text so that I can paste in partial or full UUID if I'm a support rep for a company and troubleshooting customer API integrations.

A further example of this when set up as a Ransacker within a Rails model is as follows:

ransacker :id do
  Arel.sql('lower(books.id::text)')
end

Where books.id is a UUID based PK ID.

Another constructed field example as a Ransacker would be like the following which allows us to access a key within a JSON type column:

ransacker :name do
  Arel::Nodes::InfixOperation.new(
    '->>',
    Arel.sql('countries.name_translations'),
    Arel::Nodes.build_quoted('en')
  )
end

For context where name_translations contains database stored ISO country codes for naming of things in other languages. Already agreed this is pretty advanced usage, but some sort of support for custom querying/escape hatches would be needed at some point.

A couple of other things come to mind from my Rails days and using will_paginate:

  • A customizeable helper (or documentation examples) for extracting and displaying a widget for cases like "Displaying 15 to 31 of 143 items" (when paginating with more than 15 items per page), "Displaying all items" (when working with a collection of showing 13 items for a 15 item per page), "No items to display" (when nothing is available to be shown). There are a lot of ways that we could do this, but would be useful to have an example or provide a default view that devs could take and override; we could also show the other use cases for when we would like to allow modification of the page_size param via a drop down or such
  • I18n support, in our case here provided by Gettext, for language like above, or with the typed pagination case (First, Previous, Next, Last)

Thanks again for the earlier thoughts. If any of this is interesting it might be great to form up some sort of technical roadmap to help with getting the more interesting things and top 1, 2, 3 combinations of use cases all working together. Happy to help here of course one way or another. Newish to Elixir after feeling like I had outgrown Ruby but I'm committed to building out my upcoming projects with Phoenix and in turn hoping to support the community with some of the tooling it needs as life and a busy 10 month old allows :)

from flop_phoenix.

jesselathamdev avatar jesselathamdev commented on June 14, 2024

Heya @woylie just wanted to check in to see how things were going. Saw that you had done some work around first/last links for pagination but that's applied to liveview? Any thoughts on some of the other components we were chatting about?

from flop_phoenix.

woylie avatar woylie commented on June 14, 2024

Yes, I changed the pagination helper to work with LiveView as well, and also made a change to always display the first/last link (both in LiveView and in normal templates). I worked on some filter forms on my current project recently, but I opted to do the filtering outside of Flop for now, since Flop doesn't support filters on join queries yet.

The next addition will likely be the sortable table. I have a non-sortable table helper with a spec like this:

@spec table([item], [Phoenix.HTML.safe()], (item, params -> [Phoenix.HTML.safe()]), params, keyword) :: Phoenix.HTML.safe() when item: any, params: any
table(items, headers, row_func, params, opts \\ [])

So if you want to display a list of movies, you'd have something like this:

# in the controller

def index(conn, params) do
  with {:ok, {movies, meta}} <- SomeContext.list_movies(params) do
    render(conn, "index.html", movies: movies, meta: meta)
  end
end

# in the view

def table_headers do
  ["ID", "Name", ""]
end

def table_row(%Movie{id: id, name: name}, %Plug.Conn{} = conn) do
  [id, name, link("show", to: Routes.movie_path(conn, :show, id))]
end

# in the template

<%= table @movies, table_headers(), &table_row/2, @conn %>
<%= pagination(@meta, &Routes.movie_path/3, [@conn, :index]) %>

To make the table sortable, we need to know which columns should be sortable and which field a column belongs to. One way to do that could be to pass this information in the table_headers function. Instead of passing the argument as a [Phoenix.HTML.safe()], maybe something like [Phoenix.HTML.safe() | {Phoenix.HTML.safe(), keyword}] would work. So instead of

def table_headers do
  ["ID", "Name", ""]
end

you would write something like

def table_headers do
  [
    {"ID", sortable: true, field: :id},
    {"Name", sortable: true, field: :name}
    ""
  ]
end

Alternatively, you might want to derive the sortable fields from Flop.Schema. In that case, you would have something like this in your template:

<%= table @movies, table_headers(), &table_row/2, @conn, for: SomeContext.Movie %>

And then the table headers could be defined without the sortable option (still requiring the field).

def table_headers do
  [
    {"ID", field: :id},
    {"Name", field: :name}
    ""
  ]
end

from flop_phoenix.

Related Issues (20)

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.