1

I'm using react-admin and I have the following resources:

enter image description here

So What I need from here is to add a Images and a videos resource. Something like this:

enter image description here

So as you can see in the image above,Images and Videos SHOULD come from the same endpoint which is called Post.

Now, what I showed you in the image it doesn't actually work. why? Because I don't have an Image or a Videos endpoint. Each time I click on them it will take me to http://localhost:3000/dahboard/Images or http://localhost:3000/dahboard/Videos, which again does not exist. My Posts endpoint does have the content that I need, it has images and it has videos.

What I need

What I need is something to be shown like in the image I posted. Something where I can click on Images or Videos no matter if the endpoint goes directly to http://localhost:3000/dahboard/Post. But I can't seem to find something related in the react-admin documentation.

What I currently Have

<Admin 
      layout={MyLayout} 
      theme={theme} 
      dataProvider={dataProvider}
    >
      <Resource name="Post"  {...posts} icon={ImageIcon} />
      <Resource name="Comment" {...comments} icon={ChatIcon} />
      <Resource name="User" {...users} icon={PeopleIcon} />
</Admin>

Folder Structure

|-- node_modules
|-- public
|-- src
  |---- comments
  |---- components
  |---- pages
  |---- posts
    |--- index.js
    |--- PostList.js
    |--- PostShow.js
  |---- users
    |--- index.js
    |--- UserList.js
    |--- UserShow.js
  |---- util
  |---- videos 
    |--- index.js
    |--- VideoList.js
    |--- VideoShow.js

EDIT

This is how I configured my dataProvider, I am using Hasura's data provider for this:

function DashboardPage(props) {
  const [dataProvider, setDataProvider] = useState(null);

  useEffect(() => {
    const buildDataProvider = async () => {

      const myClientWithAuth = new ApolloClient({
        uri: process.env.NEXT_PUBLIC_HASURA_GRAPHQL_ENDPOINT,
        cache: new InMemoryCache(),
        headers: {
          'x-hasura-admin-secret':
            process.env.NEXT_PUBLIC_HASURA_GRAPHQL_API_KEY,
        },
      });

      const dataProvider = await buildHasuraProvider({
        client: myClientWithAuth,
        getList: (resource, params) => {
          const {page, perPage} = params.pagination;
          const {field, order} = params.sort;
          const query = {
            sort: JSON.stringify([field, order]),
            range: JSON.stringify([(page - 1) * perPage, page * perPage - 1]),
            filter: JSON.stringify(params.filter),
          };
          const endpoint = resource === 'images' || resource === 'videos' 
            ? 'posts'
            : resource;

          const url = `${apiUrl}/${endpoint}?${stringify(query)}`;
          
          return httpClient(url).then(({ headers, json }) => ({
            data: json,
            total: parseInt(headers.get('content-range').split('/').pop(), 10),
          }));
        }
      })

      setDataProvider(() => dataProvider);
      
    };
    buildDataProvider();
  }, []);

  if (!dataProvider) return <p>Loading...</p>;

return (
    <Admin 
      layout={MyLayout} 
      theme={theme} 
      dataProvider={dataProvider}
    >
      <Resource name="Post" {...posts} icon={ImageIcon}  />
      <Resource name="Comment" {...comments} icon={ChatIcon} />
      <Resource name="User" {...users} icon={PeopleIcon} />
    </Admin>
  );
1
  • 1
    You can implement your dataProvider and replace paths inside it. Commented Oct 26, 2021 at 3:15

1 Answer 1

3

The right place to put that logic is in the dataProvider. You can map resource names to different endpoints. Something like:

const dataProvider = {
    getList: (resource, params) => {
        const { page, perPage } = params.pagination;
        const { field, order } = params.sort;
        const query = {
            sort: JSON.stringify([field, order]),
            range: JSON.stringify([(page - 1) * perPage, page * perPage - 1]),
            filter: JSON.stringify(params.filter),
        };
        const endpoint = resource === 'images' || resources = 'videos'
           ? 'posts'
           : resource; 
        const url = `${apiUrl}/${endpoint}?${stringify(query)}`;

        return httpClient(url).then(({ headers, json }) => ({
            data: json,
            total: parseInt(headers.get('content-range').split('/').pop(), 10),
        }));
    },
   // ...
}
Sign up to request clarification or add additional context in comments.

3 Comments

OMG, let me try this and I'll come back!
Hello, came back sorry. Well, this kinda works although I don't see any output out of it. I edited my post so you can see how I have it implemented
Any idea of what am I doing wrong? I'll appreciate it a lot!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.