React-Admin: map resource data before showing in List - reactjs

I want to perform additional operations on the returned elements from the API before showing them to the user. For example I have an enum field that is 0 or 1 and I would like to show some string instead of the raw value.
const List = (props: any) => (
<List {...props}>
<Datagrid rowClick="edit">
<TextField source="name" />
<TextField source="type" />
<TextField source="value" />
</Datagrid>
</List>
);
The type column is a 0 or a 1 and I would like to show a string to the user.
How can I map the data fetched by the <List> component before it gets passed to my <DataGrid>?

const YourChoices = [
{id: 0, name: 'One'},
{id: 1, name: 'Two'},
];
const YourTypeInput = (props) => {
return (
<SelectInput {...props} choices={YourChoices}/>
);
};
const List = (props: any) => (
<List {...props}>
<Datagrid rowClick="edit">
<TextField source="name" />
<TextField source="type" />
<TextField source="value" />
<YourTypeInput label="Type" source="xxxxxxx.yyyyyyyy"/>
</Datagrid>
</List>
);

Related

Show issue on React-admin, row is unclickable

Hello i'm hiring for a solution my show doesn't work on the row of my table. The cursor doesn't change to let me click on a row and even if i click nothing happened. That's my code
//in App.tsx
<Admin dataProvider={DataProvider} authProvider={authProvider}>
<Resource name="users" list={UsersList} show={UserShow}/>
</Admin>
// in users.tsx
export const UsersList = () => {
// const isSmall = useMediaQuery((theme : any) => theme.breakpoints.down("sm"));
return (
<List filters={userFilters}>
<Datagrid>
<TextField source="id" />
<TextField source="firstname" />
<TextField source="lastname" />
<EmailField source="email" />
<TextField source="phone" />
<TextField source="candidatureStatus" />
<TextField source="created_at" />
</Datagrid>
</List>
);
};
export const UserShow = () => (
<Show>
<SimpleShowLayout>
<TextField label="test" source="email" />
<TextField source="firstname" />
<TextField source="lastname" />
</SimpleShowLayout>
</Show>
)
Even if i followed the tutorial on react admin i can't display a showScreen
If you want to open the Show form when clicking on a row in the List, you need to add:
<Datagrid rowClick="show">
https://marmelab.com/react-admin/Datagrid.html#rowclick

How to get rid of shadows in the Material-UI theme

I need to get rid of shadows in MuiPaper component.
I found some solution:
for example
but they didn't work.
I can override only root component (MuiPaper) but the shadow is set by the class MuiPaper-elevation1-24.
code that render component
const List = props => (
<List {...props} title="lists" filters={<Filter />} sort={{ field: 'timestamps.createdAt', order: 'DESC' }}>
<Datagrid rowClick="show" expand={<Edit />} >
<TextField source="attributes.campaignUuid" label="Campaign Uuid" />
<TextField source="attributes.affiliateId" label="Affiliate Id" />
<DateField source="attributes.createdAt" label="Created At" showTime locales="ru-RU" sortBy="timestamps.createdAt" />
<DateField source="attributes.updatedAt" label="Updated At" showTime locales="ru-RU" sortBy="timestamps.updatedAt" />
<DeleteButton />
</Datagrid>
</List>
);
And HTML that I receive:
<div class="list-page Component-root-904">
<div class="MuiPaper-root-21 MuiPaper-elevation1-24 MuiPaper-rounded-22 MuiCard-root-740 Component-card-905"></div>
</div>
Try this:
import { withStyles, createStyles } from '#material-ui/core/styles';
const listStyles = theme => createStyles({
card: {
boxShadow: 'none',
},
});
const List = withStyles(listStyles)(({ classes, ...props }) => (
<List classes={classes} title="lists" filters={<Filter />} sort={{ field: 'timestamps.createdAt', order: 'DESC' }} {...props}>
...
</List>
);

React-admin: permissions not accessible in react.component

I am using react-admin and have incorporated the advanced tutorial "Creating and Editing a Record From the List Page". This tutorial uses react.component instead of constants. I now need to display fields based of my values in the permissions object passed by authorization. I can do this fine in constants and in the admin component but permissions is always null if I try to access it in the react.component.
class InviteCodeList extends React.Component {
render() {
const { permissions,push, classes, ...props } = this.props;
console.log('permissions');
console.log(permissions);
return (
<Fragment>
<List
{...props}
filters={<CustomFilter />}
actions={<CustomActions />}
sort={{ field: 'title', order: 'ASC' }}
>
<Datagrid>
<TextField source="id" />
<TextField source="title" />
<WithPermissions
render={({ permissions }) => (
permissions.find(f => f.resource === 'admin') !== undefined
? <TextField source="invite_code" />
: null
)}
/>
<ReferenceField source="price_list_id" reference="pricelists">
<TextField source="price_list_name" />
</ReferenceField>
<TextField source="effective_dt" />
<DateField source="expiration_dt" />
<EditButton />
</Datagrid>
</List>
Here is the new code segment. I did not check for null which is returned before the API call returns the actual data.
<Fragment>
<List
{...props}
filters={<CustomFilter />}
actions={<CustomActions />}
sort={{ field: 'title', order: 'ASC' }}
>
<Datagrid>
<TextField source="id" />
<TextField source="title" />
permissions !== null ? permissions.find(f => f.resource === 'admin') !== undefined
? <TextField source="invite_code" />
: null : null
<DateField source="expiration_dt" />
<EditButton />
</Datagrid>
</List>

React-Admin ReferenceInput issues

I am trying to reference category in my create and edit product page. Please find the code below:
const validateProduct = (values) => {
const errors = {};
if (!values.name) {
errors.name = ['Product name is required'];
}
if (!values.category) {
errors.category = ['Product category is required'];
}
return errors
};
export const ProductCreate = (props) => (
<Create {...props}>
<SimpleForm validate={validateProduct}>
<TextInput source="name" />
<ReferenceInput label="category" source="category._id" reference="categories">
<SelectInput optionText="name" />
</ReferenceInput>
<TextInput source="price" />
<LongTextInput source="description" />
<TextInput source="image" />
</SimpleForm>
</Create>
);
const ProductTitle = ({ record }) => {
return <span>Product {record ? `"${record.name}"` : ''}</span>;
};
export const ProductEdit = (props) => (
<Edit title={<ProductTitle />} {...props}>
<SimpleForm validate={validateProduct}>
<DisabledInput source="id" />
<TextInput source="name" />
<ReferenceInput label="category" source="category._id" reference="categories">
<SelectInput optionText="name" />
</ReferenceInput>
<TextInput source="price" />
<LongTextInput source="description" />
<TextInput source="image" />
</SimpleForm>
</Edit>
);
There are few issues with the ReferenceInput:
Validation does not work for ReferenceInput.
Existing category is not selected by default in the edit product page.
I want the category validation and category selection enabled in add/edit pages. How do I achieve that in React-Admin?
Thanks

Is it possible to have conditional columns in a List/DataGrid in Admin on REST?

If I apply a filter in a List component in Admin on REST, I want to only show the filtered column (TextField) once this specific filter is selected, because the filter is fuzzy and I want to see the different results at a glance. But when no filter is set, the column is supposed to be hidden.
I implemented it like this so far.
const ConditionalFilterTextField = (props) => {
const show = ... // if filter is set in URL
return (show) ? <TextField {...props} /> : null
}
...
<List {...props} filters={<MyFilter />}>
<Datagrid>
...
<ConditionalFilterTextField sortable={false} source="filter_field" label="My Label" />
...
</Datagrid>
</List>
This does work in a way, but then again not really. It shows the label of the column and an empty space when I return null (when the filter is not set and the column is supposed to be hidden).
How can I control visibility of a TextField depending on whether a filter is set or not? How can I force a rerender of the List when I want to add a column?
Edit:
This is similar to your answer, #Gildas, but doesn't work for me. Some detail might be wrong?
in itemList.js
class ItemList extends Component {
render() {
const props = this.props
// Find out if current filter is source of field.
const filter = props.itemsFilters
const showFieldA = (filter && filter.fieldA) ? true : false
return <List {...props} filters={<ItemsFilter />} perPage={50}>
<Datagrid>
<ReferenceField sortable={false} source="id" reference="items" linkType="show">
<TextField source="fieldB" />
</ReferenceField>
<TextField sortable={false} source="fieldC" />
<TextField sortable={false} source="fieldD" />
<DateField sortable={false} source="fieldE" />
{ (showFieldA === true) ? <TextField sortable={false} source="fieldA" /> : null }
<ShowButton />
<EditButton />
</Datagrid>
</List>
}
}
const ItemsFilter = (props) => (
<Filter {...props}>
<TextInput label="FilterSearch" source="q" />
<TextInput label="FilterA" source="fieldA" />
</Filter>
)
function mapStateToProps(state) {
return {
itemsFilters: state.admin.resources.items.list.params.filter
}
}
export default connect(mapStateToProps)(ItemList)
...
in App.js
<Resource name="items" list={ItemList} show={ItemShow} edit={ItemEdit} />
const MyList = (props) => {
const show = ... // if filter is set in URL
return (
<List {...props} filters={<MyFilter />}>
<Datagrid>
...
{show ? <TextField {...props} /> : null}
...
</Datagrid>
</List>
);
}

Resources