BowlingX/ra-postgraphile

Ability to use alternative filter operators

christiaanwesterbeek opened this issue · 11 comments

I'm transitioning from a custom dataprovider based on ra-data-graphql-simple to ra-postgraphile. A couple of my Lists have filters that need to query a field case insensitively. Also, I'd like to use some of the other filter operations that are laid out here.. https://github.com/graphile-contrib/postgraphile-plugin-connection-filter#string

Currently ra-postgraphile uses like ... or equalTo ... internally. I'd like to be able to use filter using any of the other operators of postgraphile-plugin-connection-filter.

I'd like to discuss if this would be a welcome feature and discuss how to implement it.

I've seen this solution <TextInput source="name@eq" /> where the part after the @ could be the filter operator. We could probably expand on this. Maybe there are other established solutions for custom filtering in ra dataproviders that we can copy.

I'm happy to contribute with coding. I've done some customisation on ra dataproviders for postgrest before.

I like the name@filter solution :). Feel free to create a pull request. I could imagine we need to create a mapper and implement the filters for all the different operators.

I've been browsing through all of the dataProviders listed here and found one other that uses the same technique

const UserFilter = (props) => (
  <Filter {...props}>
    <TextInput label="Name" source="firstname||starts" alwaysOn />
    <TextInput label="Email" source="email" />
    <InputRow source="_created_range" label="Cretaion date">
      <DateInput source="_created_range.created||gte" label="From" options={{ format: 'dd/MM/YYYY' }} />
      <DateInput source="_created_range.created||lte" label="To" options={{ format: 'dd/MM/YYYY' }} />
    </InputRow>
  </Filter>
);

Both of these solutions leverage the source attribute of the input to formulate the filter operator. Other dataproviders like aor-postgrest-client use the value of the input to formulate the filter operator. I think the latter is more powerful, because you can get a lot more expressive with the value than you can with a fancy source-string (with the @ and such).

The value

So, I 'd like to investigate using the value of inputs in the filter to formulate filter operators. You would think that that's tricky since a <TextInput /> produces strings as values. But we can get them to produce objects as values using the parse method available for Inputs. Head to https://marmelab.com/react-admin/Inputs.html --> "Transforming Input Value to/from Record" for documentation on parse.

This would actually work with very little change to ra-postgraphile to pickup the object created by the parse method.

import React from 'react';
import { Filter, TextInput } from 'react-admin';

const ilike = {
    // converts the input to the filter
    parse: value => ({
        ilike: value,
    }),
    // converts the filter back to the input
    format: obj => obj && obj.ilike,
};

const MyListFilter = props => {
    return (
        <Filter {...props}>
            <TextInput
                source="name"
                resettable
                alwaysOn
                parse={ilike.parse}
                format={ilike.format}
            />
        </Filter>
    );
};

export default MyListFilter;

With this solution we basically need to do 2 things to make this work.

  1. Create a bunch of objects with parse/format pairs for each operator in postgraphile-plugin-connection-filter and include them in this repository ready to be imported by our apps. Like so maybe: import { ilike } from 'ra-postgraphile';
  2. Make sure that ra-postgraphile uses the object (generated by the parse method) to create the filter. Basically we need to change something here: https://github.com/BowlingX/ra-postgraphile/blob/master/src/filters.ts

Thoughts?

Thank you for the proposal :) I like the idea because it's "typesafe" and will propably less error prone :). Feel free to start a pull request :).

hjr3 commented

I hacked a poc of this together and it is working out well for me. @christiaanwesterbeek if you want help with the PR, please let me know.

@hjr3 I'm ready to contribute to the PR. Can I commit to your fork?

PS: My TypeScript skills are limited at the moment

tr11 commented

@hjr3, I'm also interested in contributing to the PR. Namely, I'd like to add support for the postgraphile-plugin-fulltext-filter plugin, which creates a matches filter for tsvector types.

@hjr3 I've committed my contribution to a fork on this work and just created a PR that you can merge in.

If you require anything let me know. I'm a bit busy with other projects but happy to help reviewing.

braco commented

What are your thoughts on this?
https://github.com/lovelysystems/ra-data-postgraphile
It looks like a lot of this stuff is already implemented there.

Cool :). Yeah, seems like a lot of use cases are covered there. I have a bit of time this week, so I will work on a few things.

Fixed by #17