What I have.
I have few resources in my project -> users and user_activity.
Edpoint for getting user_activity looks like this:
curl base_url/rpc/user_activity?id=user_id -H "Content-Type: application/json" -X GET
Some React admin code
<Resource
name="user"
options={{ label: 'Users' }}
list={ UsersList }
create={ UsersCreate}
edit={ UsersEdit }
show={ UsersShow }
/>
<Resource name="user_activity"/>
What I need.
On the edit and show User page to put the button - "Activity", onclick on which I need to go to another page and show there table of User's Activity according to user_id.
I was thinking that for showing data from user_activity reasource I can use or new useQuery hook, but it should get somehow user_id as an argument, then how to pass it? Also was cheking as I understood it shows the data connected by the key from different resource but it show it at the same component and I need it to be on separate page.
How to do it?
What do you think is the best way to create a page and with what component inside in order to show the user_activity by user_id from another page?
Can you use a "ReferenceManyField" ?
I do something very similair using tabs instead of a new page.
For example:
<TabbedShowLayout>
<Tab label="activity" path="activity">
<ReferenceManyField
addLabel={false}
reference="activity"
target="user_id"
sort={{ field: 'Date', order: 'DESC' }}
>
<Datagrid>
<DateField source="Date" label="Date" showTime />
<TextField source="Type" label="Type" />
<TextField source="Result" label="Result" />
</Datagrid>
</ReferenceManyField>
</Tab>
</TabbedShowLayout>
Don't forget to add "activity" to your resources in
My dataprovider translate it to:
http://localhost:3001/activity?filter=%7B%22user_id%22%3A%XXXXX%22%7D&range=%5B0%2C24%5D&sort=%5B%22Date%22%2C%22DESC%22%5D
Related
I have a list of resources, which I understood that must be the entities for which we have the CRUD operations:
The problem is that inside the entity page I want to use 2 tabs (components), one for the list of the entity and one for a list of aggregated data based on the entity. The problem is with the second, because I was required to write a custom graphql query, but both components use the same source (first list).
<ProtectedResource
name={RESOURCES.Product}
list={Product.homepage}
icon={StarHalfIcon}
options={{ label: translate('Products') }}
/>
Products.js is a hook which returns this:
<TabbedForm redirect={`/${RESOURCES.Product}`}>
<FormTab label={translate('Lines')}>
<ReferenceManyField reference={RESOURCES.Product} target="" label="" fullWidth {...paginationProps('id')}>
<ProductsList {...props} />
</ReferenceManyField>
</FormTab>
<FormTab label={translate('Aggregated Lines')} path="/aggregates">
<ReferenceManyField reference={RESOURCES.Product} target="" label="" fullWidth {...paginationProps('id')}>
<ProductAggregatesList {...props} />
</ReferenceManyField>
</FormTab>
</TabbedForm>
In reality, should hit 2 queries: getAllProducts and getAggregatedProducts. Based on fetchType and resource, I can rewrite the query which I want to execute (in frontend), but I can not catch the data and send to the specific component.
if (fetchType === GET_MANY_REFERENCE && resource === RESOURCES.Product)
return getAggregatedProducts(resource, params);
And GET_LIST fetch type will be used for first tab.
If I create another resource, for AggregatedProducts, there will throw an error because AggregatedProducts is not known in backend's schema.
I have a question regarding react-admin. So I'm building this admin List which Hasura-graphQL. I am able to render Images with the ImageField component which I am using:
<ImageField label="Image" source="image" sortByOrder="DESC"/>
And which I have no problems rendering. But the issue comes when I need to render a video that comes in a URL from my graphQL schema. Something like this:
"video": "https://myappvideo.blob.core.windows.net/posts/post_93753139-524a-4c85-a0fc-d40b47bd95f5.mp4?se=2030-12-31&sp=rwdlac&sv=2018-03-28&ss=btf&srt=sco&sig=oeyHYsiWC79a1z7fcgsPPdJzeC499t%2BwPkbImcctpJE%3D",
"id": 471
},
{
"video": null,
"id": 493
},
{
"video": "https://myappvideo.blob.core.windows.net/posts/post_f9c59f2f-3d2e-4c63-ae1e-65e5324866ad.mp4?se=2030-12-31&sp=rwdlac&sv=2018-03-28&ss=btf&srt=sco&sig=oeyHYsiWC79a1z7fcgsPPdJzeC499t%2BwPkbImcctpJE%3D",
"id": 476
},[...]
How can render videos in my react-admin list? Something where I can show the videos and I can click and reproduce?
React-admin has a way to render Images but I can see something similar for videos.
Any help would be appreciated a lot!
EDIT
This is how I'm actually trying to make this work:
<Datagrid>
<TextField label="Post ID" source="id" sortByOrder="ASC" />
//I am using FileField for this, but it does not work
<FileField label="Content" source="video" rel="video" sortByOrder="ASC" />
<TextField label="Content Type" />
<UserSum source="id" />
<SimpleForm {...props} label="Flagged">
<ApproveData source="id" />
</SimpleForm>
<DateField label="Posted On" source="createdAt" showTime />
<PostListActionToolbar>
<ShowButton label="Details" color="secondary" />
<EditButton label="Archive" color="secondary" />
</PostListActionToolbar>
</Datagrid>
Ok, I just figure out how to do this. Indeed react-admin does not have a way to render videos. So in this case you'll have to create your own component.
Step 1
Is to create the function:
const VideoField = (props) => {
const record = useRecordContext(props);
return <video src={`${record.video}`} controls width="320" height="240"></video>;
}
In this case, you'll have to interpolate the video record inside the video tag. I added the controls and the width and height to add more view on the video
Step 2
You can add a default label into it like this:
VideoField.defaultProps = { label: 'Video' };
This is necessary since it will label your content on the top side of the list.
Step 3
Then add your function in to a component inside the datagrid and you'll be having something like this:
Add it like this on your datagrid
<Datagrid>
<TextField label="Post ID" source="id" sortByOrder="ASC" />
<VideoField source="video" />
<TextField label="Content Type" />
</Datagrid>
I have a react-admin based site working nicely.
Though i have an issue with the sidebar menu. If i click one of the items twice it clears all the form inputs. This is a link to an edit form of the resource item (in this case the current user profile):
<MenuItemLink to={"/users/" + user.id} primaryText="Profile" leftIcon={createElement(UserIcon)} onClick={onMenuTap}/>
with resource that looks like:
<Resource name="users" list={UserList} edit={UserEdit} create={UserCreate} icon={UserIcon} />
where UserEdit is
export const UserEdit = (props) => {
<Edit title={<UserEmail />} actions={<UserEditActions />} {...props}>
<SimpleForm validate={validateUserSave}>
<DisabledInput source="email"/>
<TextInput label="First Name" source="firstName" />
<TextInput label="Last Name" source="lastName" />
...
on first click all the inputs are populated from my REST api, but on 2nd tap (menu item selected) - all the form values are cleared...
Any ideas?
It is indeed a bug, I opened an issue on React Admin:
[#2291] Double-click on a Icon from the Menu reset the edition form
[#2322] Fix resetform when navigating to same page
A fix will be published with react-admin#2.3.2!
Thanks for reporting the issue.
I am new using admin-on-rest framework, I need to make nested form working.
I have two models show and song.show() can have multiple songs. I have show edit form it will work as expected.
I need to add a song form inside show edit form, so I can add multiple songs for each show.
I tried all ways but i am not able to get it done.
This is my code:
<Edit title="Edit Show" {...this.props}>
<SimpleField>
<TextInput source="name" style={{ display: 'inline-block' }} />
//here need to add song add form without reloading page
//this is songs grid
<ReferenceManyField reference="songs" target="show_id" label="Set List" perPage={5} >
<Datagrid>
<TextField source="song_name" />
<EditButton />
<DeleteButton />
</Datagrid>
</ReferenceManyField>
//Here need to add song form, so i can add songs
</SimpleField>
</Edit>
How can I achieve this?
Not sure if that answers your question.. if songs pre-exist then you just need to do that:
<Edit title="Edit Show" {...this.props}>
<TextInput source="name" style={{ display: 'inline-block' }} />
<ReferenceArrayInput label="Songs" source="songs_property_on_show" reference="songs" allowEmpty>
<SelectArrayInput optionText="song_name" translate={false}/>
</ReferenceArrayInput>
</Edit>
if you want to create them on the fly while you are creating the show or in other words have a form inside the other this needs to be done in a custom way (using redux-form) as commented under my question: how to create an entity inside another in the same form using admin-on-rest?
Here is the ref : Admin-on-Rest
in app.js :
<Resource name="customers" list={CustomerList} icon={UserIcon} edit={CustomerEdit} create={CustomerCreate}/>
in customer.js :
<TextInput source="firstname" />
<ReferenceInput label="Partner" source="id" reference="partners" >
<AutocompleteInput optionText="name" />
</ReferenceInput>
<TextInput source="email" />
The problem is autocomplete not shown, but I check in log data retrieved from API end point /partners
And if I change reference to reference="customers", data and autocomplete shown.
Help please ??
You need another <Resource> for the relationship, even empty:
<Resource name="customers" list={CustomerList} icon={UserIcon} edit={CustomerEdit} create={CustomerCreate}/>
<Resource name="partners" />
It is well documented for <ReferenceField> (see the note), perhaps it needs the same note for <ReferenceInput>.
You <ReferenceInput reference="..."> needs to match the <Resource name="..."> for this to work. So this is the reason why reference="customers" worked for you.
If you want to get data from customers endpoints, but you want the label to be Partner you can specify it as label attribute on your ReferenceInput component, e.g. <ReferenceInput label="Partner" ...>.
The problem is probably the way you're importing your 'ReferenceInput' object. I had the same issue while creating my app and had no idea what is the problem.
Check your import line and if it looks like this:
import {ReferenceInput} from "../../src/mui/input/ReferenceInput";
then change it to look this way:
import ReferenceInput from '../../src/mui/input/ReferenceInput';
Hope that helps you!