Skip to content

Instantly share code, notes, and snippets.

@MichalKalita
Created August 14, 2020 14:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MichalKalita/95c67cd40362c72a868c60085a8d3a72 to your computer and use it in GitHub Desktop.
Save MichalKalita/95c67cd40362c72a868c60085a8d3a72 to your computer and use it in GitHub Desktop.
Ability to ILIKE find for ra-data-hasura
/*
This is almost copy of ra-ui-materialui/src/list/Filter.tsx
Filters in array of props.searchSources are changed to ILIKE %value%
*/
import * as React from "react";
import { FC, ReactNode } from "react";
import { makeStyles } from "@material-ui/core/styles";
import { sanitizeListRestProps, useListContext } from "ra-core";
import PropTypes from "prop-types";
import { ClassesOverride, FilterButton, FilterForm } from "ra-ui-materialui";
import _ from "lodash";
const useStyles = makeStyles(
{
button: {},
form: {},
},
{ name: "RaFilter" }
);
export interface FilterProps {
context?: string;
variant?: string;
classes: ClassesOverride<typeof useStyles>;
children: ReactNode;
searchSources: string[];
}
const SearchFilter: FC<FilterProps> = props => {
const classes = useStyles(props);
const {
resource,
showFilter,
hideFilter,
setFilters: _setFilters,
displayedFilters,
filterValues: _filterValues,
} = useListContext(props);
const handleSetFilters = (
filters: Record<string, any>,
displayedFilters: any
) => {
Object.keys(filters).forEach(filterInput => {
if (props.searchSources.includes(filterInput)) {
filters[filterInput] = { _ilike: `%${filters[filterInput]}%` };
}
});
_setFilters(filters, displayedFilters);
};
const filterValues = React.useMemo(() => {
const result = _.cloneDeep(_filterValues);
Object.keys(result).forEach(filterInput => {
if (props.searchSources.includes(filterInput)) {
result[filterInput] = result[filterInput]?._ilike
?.replace(/^%/, "")
?.replace(/%$/, "");
}
});
return result;
}, [_filterValues, props.searchSources]);
console.log(_filterValues, filterValues);
const renderButton = () => {
const {
classes: classesOverride,
context,
children,
variant,
...rest
} = props;
return (
<FilterButton
className={classes.button}
resource={resource}
filters={React.Children.toArray(children)}
showFilter={showFilter}
displayedFilters={displayedFilters}
filterValues={filterValues}
{...sanitizeListRestProps(rest)}
/>
);
};
const renderForm = () => {
const { classes: classesOverride, context, children, ...rest } = props;
return (
<FilterForm
className={classes.form}
resource={resource}
filters={React.Children.toArray(children)}
hideFilter={hideFilter}
displayedFilters={displayedFilters}
initialValues={filterValues}
setFilters={handleSetFilters}
{...sanitizeListRestProps(rest)}
/>
);
};
return props.context === "button" ? renderButton() : renderForm();
};
SearchFilter.propTypes = {
children: PropTypes.node,
classes: PropTypes.object,
context: PropTypes.oneOf(["form", "button"]),
};
export default SearchFilter;
export const ProductList = props => (
<List {...props} filters={<ProductFilter />}>
<Datagrid rowClick="edit">
{* not related to this example *}
</Datagrid>
</List>
);
const ProductFilter = props => (
// In searchSource is sources where value will be searched as ILIKE %value%
<SearchFilter {...props} searchSources={["title"]}>
<SearchInput source="title" alwaysOn />
</SearchFilter>
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment