您可以与客户端排序和过滤共享您的 dataProvider 吗?

Can you share your dataProvider with client-side sorting and filtering?

我有一个基本的 REST API 我正在使用(没有查询,没有分页)并且我将它很好地集成到 React Admin 中,具有编辑、显示和创建操作。一切都很好。但是,我的 API 没有任何过滤或排序功能,因此 Datagrid 的功能已失去,因为我无法搜索或对列进行排序。

我知道我需要实现客户端功能来在自定义 dataProvider 中过滤和排序 API 自己。除了从头开始构建这一切,任何人都可以与我分享他们的自定义 dataProvider 已经有本地排序、过滤器等我可以适应而不是从头开始构建吗?

或者,我昨晚实现了 Tubular for React,我喜欢它的易用性,但它缺乏与 React Admin 的良好集成。有人在 React Admin 中实现了 Tubular 吗?你是如何实现它的?

提前感谢您的帮助!!

这是我为我们的项目编写的dataProvider。所有过滤、排序、分页都在客户端完成。

import { fetchUtils, DataProvider } from 'ra-core';

const dataProvider = (apiUrl : string, httpClient = fetchUtils.fetchJson) : DataProvider => ({
    getList: async (resource, params) => {
        const { json } = await httpClient(`${ apiUrl }/${ resource }`);
        const feedFilter = params.filter["feed"];
        const stateFilter = params.filter["state"];

        const result = json
            .filter(e => {
                if (!feedFilter) {
                    return true;
                }
                return e.feed.includes(feedFilter.toUpperCase());
            })
            .filter(e => {
                if (!stateFilter) {
                    return true;
                }
                return e.state === stateFilter;
            });

        const { field, order } = params.sort;
        result.sort(dynamicSort(field, order));

        const { page, perPage } = params.pagination;
        const showedResult = result.slice((page - 1) * perPage, page * perPage);

        return {
            data: showedResult.map((resource : { feed : string; }) => ({ ...resource, id: resource.feed })),
            total: result.length,
        };
    },

    getMany: async (resource) => {
        const url = `${ apiUrl }/${ resource }`;
        const { json } = await httpClient(url);
        return ({
            data: json.map((resource : { feed : string; }) => ({ ...resource, id: resource.feed })),
        });
    },

    getManyReference: async (resource) => {
        const url = `${ apiUrl }/${ resource }`;

        const { headers, json } = await httpClient(url);
        return ({
            data: json.map((resource : { feed : string; }) => ({ ...resource, id: resource.feed })),
            total: parseInt(headers.get('X-Total-Count') || "", 10),
        });
    },

    getOne: (resource, params) =>
        httpClient(`${ apiUrl }/${ resource }/${ params.id }`).then(({ json }) => ({
            data: json,
        })),

    update: (resource, params) =>
        httpClient(`${ apiUrl }/${ resource }/${ params.id }`, {
            method: 'PUT',
            body: JSON.stringify(params.data),
        }).then(({ json }) => ({ data: json })),

    updateMany: async (resource, params) => {
        const { json } = await httpClient(`${ apiUrl }/${ resource }`, {
            method: 'PUT',
            body: JSON.stringify(params.data),
        });
        return ({ data: json });
    },

    create: (resource, params) =>
        httpClient(`${ apiUrl }/${ resource }`, {
            method: 'POST',
            body: JSON.stringify(params.data),
        }).then(({ json }) => ({
            data: { ...params.data, id: json.id },
        })),

    delete: (resource, params) =>
        httpClient(`${ apiUrl }/${ resource }/${ params.id }`, {
            method: 'DELETE',
        }).then(({ json }) => ({ data: json })),

    deleteMany: async (resource, params) => {
        const { json } = await httpClient(`${ apiUrl }/${ resource }`, {
            method: 'DELETE',
            body: JSON.stringify(params.ids),
        });
        return ({ data: json });
    },
});

function dynamicSort(property : string, order : string){
    let sortOrder = 1;
    if (order === "DESC") {
        sortOrder = -1;
    }
    return function (a : any, b : any){
        let aProp = a[property];
        let bProp = b[property];
        if (!a.hasOwnProperty(property)) {
            aProp = ''
        }
        if (!b.hasOwnProperty(property)) {
            bProp = ''
        }
        const result = (aProp < bProp) ? -1 : (aProp > bProp) ? 1 : 0;
        return result * sortOrder;
    }
}

const cacheDataProviderProxy = (dataProvider : any, duration = 5 * 60 * 1000) =>
    new Proxy(dataProvider, {
        get: (dataProvider, name) => (resource : string, params : any) => {
            if (name === 'getOne' || name === 'getMany' || name === 'getList') {
                return dataProvider.name(resource, params).then((response : { validUntil : Date; }) => {
                    const validUntil = new Date();
                    validUntil.setTime(validUntil.getTime() + duration);
                    response.validUntil = validUntil;
                    return response;
                });
            }
            return dataProvider.name(resource, params);
        },
    });

export default cacheDataProviderProxy(dataProvider);