avo icon indicating copy to clipboard operation
avo copied to clipboard

[RFC] Dynamic filters 2.0

Open adrianthedev opened this issue 1 year ago • 3 comments
trafficstars

The Dynamic filters feature is a powerful and beautiful way of letting users query data.

We'd love to give the developer an API with which they can further customize the filters. Some of the things we'd like to have customizable:

  • field (text, number, combobox, date)
  • conditions (is, is not, is withing, etc.)
  • suggestions (options)
  • query logic. give the developer the raw power to make the query what they want.

Let's also change the API in which they are declared. It's clear to me that just calling filterable is not enough. It's a good "easy" way to do it, but we need more power.

Things to consider with this new API/DSL:

  • should we build them on the resource?
  • should we build them in a separate file?
### Related issues
- [ ] https://github.com/avo-hq/avo/issues/2802
- [ ] https://github.com/avo-hq/avo/issues/2634
- [ ] https://github.com/avo-hq/avo/issues/2621

Examples

Pseudo-API below. Not final.

field :name, as: :select, filterable: {
  conditions: [:is, :is_not],
  options: -> { User.states }
}
self.dynamic_filters = -> {
  filters: [
    {
      attribute: :name,
      type: :select,
      conditions: [:is, :present, :blank, :nil],
      field: {
        type: :select,
        options: [:one, :two, :three
      }
    }
  ]
}

adrianthedev avatar Dec 20 '23 15:12 adrianthedev

Experiments


  self.dynamic_filters = {
    fields: [:status, :state],
    filters: [
      # hierarchy
      # - database
      # - field
      # - dynamic_filters
      avo_filter(attribute: :name, type: :select),
      Avo::Filter.new(attribute: :name, type: :select),
      Avo::Filter.new(attribute: :name, type: :select),
      Avo::Filter.new(attribute: :name, type: :select),
      Avo::Filter.new(attribute: :name, type: :select),
      {
        attribute: :name,
        type: :select,
        conditions: [:is, :present, :blank, :nil],
        field: {
          type: :select,
          options: [:one, :two, :three]
        },
        # fields: [{
        #   id: :first_name,
        #   type: :select,
        #   options: [:one, :two, :three]
        # },{
        #   id: :last_name,
        #   type: :select,
        #   options: [:one, :two, :three]
        # }]
      },
      {
        attribute: :last_name,
        type: :select,
        conditions: [:is, :present, :blank, :nil],
        field: {
          type: :select,
          options: [:one, :two, :three]
        }
      }
    ]
  }

filterable: Avo::Filter.new(attribute: :name, type: :select),

adrianthedev avatar Apr 17 '24 07:04 adrianthedev

@adrianthedev do you plan for some lazy loading version? Or even a belongs-to type?

jetienne avatar Apr 17 '24 07:04 jetienne

@adrianthedev do you plan for some lazy loading version? Or even a belongs-to type?

Yes @jetienne. Me and the team are going to talk about and build some kind of lazy-loaded select somehow which can be applied system-wide. We'll evaluate https://github.com/josefarias/hotwire_combobox. Looks promising.

adrianthedev avatar Apr 17 '24 12:04 adrianthedev