Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[docs] How to decorate the ra-data-feathers data provider #176

Open
strarsis opened this issue Mar 12, 2022 · 4 comments
Open

[docs] How to decorate the ra-data-feathers data provider #176

strarsis opened this issue Mar 12, 2022 · 4 comments

Comments

@strarsis
Copy link

strarsis commented Mar 12, 2022

The ra-data-feather provider can't be decorated (for extending or changing its behavior) the usual way (as the example in the react-admin does).
The reason is that the ra-data-feather provider returns a function instead of a JavaScript object with member methods.

That function needs to be wrapped by a decorator function:

import { UPDATE } from 'react-admin';

const addUploadCapabilities = function (dataProvider) {
    return function(type, resource, params) {

        // e.g. for "categories" resource and "UPDATE" type only:
        if(resource === 'categories' && type === UPDATE) {
            // extra stuff, modify `params`/`resource`
            // [...]
            // return [...]; // return to completely skip the `dataProvider` in this case
        }

        // call the underlying `ra-data-feathers` provider
        return dataProvider(type, resource, params);
    }
}
@strarsis strarsis changed the title [docs] How to decorate the data provider [docs] How to decorate the ra-data-feathers data provider Mar 12, 2022
@josx
Copy link
Owner

josx commented Mar 15, 2022

A simple way to do it, it is after getting the dataProvider.

import feathersClient from './feathersClient';
import { restClient, authClient } from 'ra-data-feathers';
const restClientOptions = {}; 
const dataProvider = restClient(feathersClient, restClientOptions); 

@strarsis
Copy link
Author

@josx: Thanks, but the 2nd code excerpt in your post is incorrectly formatted and doesn't render.

@josx
Copy link
Owner

josx commented Mar 15, 2022

I deleted the 2nd excerpt, was a typo.

Just with above lines and following this https://marmelab.com/react-admin/DataProviders.html#extending-a-data-provider-example-of-file-upload you can do it.

The idea is getting an instance of the provider and then extending.

@strarsis
Copy link
Author

strarsis commented Mar 15, 2022

@josx: Using the approach in the docs results in an error:

Error: Unknown dataProvider function: getList

The reason is that the ra-data-feathers data provider isn't a JavaScript object but rather a function,
hence the member method getList cannot be found.

const dataProvider = restClient(feathersClient, restClientOptions);

const myDataProvider = {
    ...dataProvider,
    update: (resource, params) => {
        if (resource !== 'posts' || !params.data.pictures) {
            // fallback to the default implementation
            return dataProvider.update(resource, params);
        }
        /**
         * For posts update only, convert uploaded image in base 64 and attach it to
         * the `picture` sent property, with `src` and `title` attributes.
         */
        
        // Freshly dropped pictures are File objects and must be converted to base64 strings
        const newPictures = params.data.pictures.filter(
            p => p.rawFile instanceof File
        );
        const formerPictures = params.data.pictures.filter(
            p => !(p.rawFile instanceof File)
        );

        return Promise.all(newPictures.map(convertFileToBase64))
            .then(base64Pictures =>
                base64Pictures.map(picture64 => ({
                    src: picture64,
                    title: `${params.data.title}`,
                }))
            )
            .then(transformedNewPictures =>
                dataProvider.update(resource, {
                    ...params,
                    data: {
                        ...params.data,
                        pictures: [
                            ...transformedNewPictures,
                            ...formerPictures,
                        ],
                    },
                })
            );
    },
};


const authProvider = authClient(feathersClient, authClientOptions);

render(
    <React.StrictMode>
          <Admin
              dataProvider={myDataProvider}
[...]

Treating the ra-data-feathers data provider as a function however works:

const addUploadCapabilities = function (dataProvider) {
    return function(type, resource, params) {

        // e.g. for "categories" resource and "UPDATE" type only:
        if(resource === 'categories' && type === UPDATE) {
            // extra stuff, modify `params`/`resource`
            // [...]
            // return [...]; // return to completely skip the `dataProvider` in this case
        }

        // call the underlying `ra-data-feathers` provider
        return dataProvider(type, resource, params);
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants