Search code examples
reactjsreact-admin

How to push data feed to Dashboard to be able create charts on it in react-admin?


I have a basic dashboard.js which was on the Tutorial of React-admin.

import React from 'react';
import Card from '@material-ui/core/Card';
import CardContent from '@material-ui/core/CardContent';
import CardHeader from '@material-ui/core/CardHeader';

export default () => (
    <Card>
        <CardHeader title="Welcome to the administration" />
        <CardContent>Juhejj ez is mukodik!</CardContent>
    </Card>
);

Where can I find any documentation on how to push the data that's coming from my App.js < Resource > (from my Rest API) to dashboard?

I want to create Widgets, Charts onto my admin dashboard, but everything I've found so far was about creating a simple Dashboard with fake data in the dashboard.js.

const data = [{ bla: 1, bla2: 2 }];

My App.js looks like this:

import React from 'react';
import { Admin, Resource, mergeTranslations, ListGuesser } from 'react-admin';
import { AdList } from './ads/AdsList';
import { AdEdit } from './ads/AdsEdit';
import { PostCreate } from './ads/posts';
import { LeadList } from './leads/leads';
import { UserList, UserShow, UserEdit, UserCreate } from './users/users';
import { ClickList, ClickMonthly, ClicksmonthlyList } from './clicks/clicks';
import PostIcon from '@material-ui/icons/Book';
import UserIcon from '@material-ui/icons/Group';
import Dashboard from './dashboard/Dashboard';
import authProvider from './authprovider/authProvider';
import jsonServerProvider from './dataprovider/rest';
import { reducer as tree } from 'ra-tree-ui-materialui';
import englishMessages from 'ra-language-english';
import treeEnglishMessages from 'ra-tree-language-english';

const messages = {
    'en': mergeTranslations(englishMessages, treeEnglishMessages),
};

const dataProvider = jsonServerProvider('http://my.api.to/api/v1/');
const App = () => (
    <Admin dashboard={Dashboard} authProvider={authProvider} dataProvider={dataProvider} locale="en" messages={messages} customReducers={{ tree }}>
    {permissions => [
        <Resource name="ads" options={{ label: 'Hirdetések' }} list={AdList} edit={AdEdit} create={PostCreate} icon={PostIcon}/>,
        permissions === 'admin' ? <Resource name="users" options={{ label: 'Felhasználók' }} list={UserList} show={UserShow} edit={UserEdit} create={UserCreate} icon={UserIcon}/> : null,
        <Resource name="clicks" options={{ label: 'Legutóbbi kattintások' }} list={ClickList} />,
        <Resource name="clicksmonthly" options={{ label: 'Havi összesítés' }} list={ClicksmonthlyList} />,
        <Resource name="leads" options={{ label: 'Legutóbbi leadek' }} list={LeadList} />,
        <Resource name="sites" />

]}
    </Admin>
);

export default App;

Solution

  • There are two ways to do that:

    One is doing it like in our official demo (source), where we call the dataProvider directly, without using redux. You call it like you would for a classic fetch (maybe inside your componentDidMount). Something like:

    dataProvider(GET_LIST, 'commands', {
        filter: { date_gte: aMonthAgo.toISOString() },
        sort: { field: 'date', order: 'DESC' },
        pagination: { page: 1, perPage: 50 },
    })
        .then(response => {
            this.setState({ commands: response.data });
        });
    

    The downside of this approach is that you'll have to handle errors, notifications, etc. by yourself.

    The other way would be to use react-admin redux action creators to do the same thing but leveraging its side effects handling (notifications on errors, etc.). This time, you have to make your <Dashboard> a connected component:

    import { connect } from 'react-redux';
    import { crudGetList } from 'react-admin';
    
    const mapStateToProps = state => {
        const commandState = state.admin.commands;
    
        // Is an object where keys are the commands identifiers
        // and the values are the command
        const commandsByIds = commandState.data;
    
        return {
            commands: Object.values(commandsByIds),
        }
    }
    
    const mapDispatchToProps = {
        crudGetList,
    }
    
    const ConnectedDashboard = connect(mapStateToProps, mapDispatchToProps)(Dashboard);
    

    You would then call the crudGetList in your componentDidMount too:

    componentDidMount() {
        this.props.crudGetList(
            'commands', // resource name
            { page: 1, perPage: 50 }, // pagination
            { field: 'date', order: 'DESC' }, // sorting
            { date_gte: aMonthAgo.toISOString() } // filters
        );
    }
    

    Final notes:

    We are aware the documentation could be improved for those use cases. The good news is that we are going to make it easier soon (probably in the 2.8 release): See https://github.com/marmelab/react-admin/pull/2899