How do i refresh the sidebar menu after loading resources dynamically in react-admin - react-admin

I am working on an application using react-admin, where each registered user will have it's own set of resources which are dynamically loaded, we don't know the exact resources upfront. Users register and login using Auth0. The data is fetched from Hasura. The solution is based on the following example to load the resources: https://marmelab.com/react-admin/Admin.html#unplugging-the-admin-using-admincontext-and-adminui
Loading the resources dynamically is working (see snippet below), however i need to refresh the page manually in order to see the resources in the sidebar menu, while the sidebar menu must be updated as soon as the dynamic resources are available. After logging out and logging back in, the resources are again not visible and a refresh is required again.
function AsyncResources() {
...
return (
<AdminUI
title="Hasura Dashboard"
dashboard={Dashboard}
history={history}
loginPage={LoginPage}
layout={Layout}
>
{resources.map(resource => (
<Resource name={resource.name} key={resource.name} options={getOptions(resource.name)} list={getList(resource.name)} />
))}
<Resource /> { /* Without this Resource, the initial page doesn't load */ }
</AdminUI>
);
}
I had a look at the following issues regarding the same topic, but i couldn't find a definite solution to my specific problem: https://github.com/marmelab/react-admin/issues/5177
with answer: "Basically you write components for every resource but only enable what you want." This is not a solution for me because that would mean i have to manually add every single resource of every new registered user.
I already created a custom Menu to see if that would help, but shows the same behaviour as the default Menu.
How can i make sure the dynamic loaded resources are visible in the menu without the user having to refresh the window after logging in?

Related

React Admin custom route to a Show view

I have an application with more than one show view for a resource. This is because there are different "views" on our complex "user" resource.
I have tried to add the path
<CustomRoutes>
<Route path="/customUserView/:id/show" element={(props) => <CustomShow id={props.match.params.id} resource={'user'}/>} />
</CustomRoutes>
My CustomShow view works perfectly when part of the react admin routes (placed as a show={CustomShow} in a regular resource component, but I can't seem to get it to work outside, in a CustomView.
Thanks for the help
If you are building your CustomShow component based on the standard Show component,
then it requires passing some of the parameters to it (for example, record) via ShowContext.
An implementation based on the RecordContextProvider component may be suitable for you, there is an example here: "SimpleShowLayout - Displays Fields In A Stack".

Add "forgot password" link to react-admin's login page

I am building an admin web interface using react-admin and at the moment, I am trying to find a way to add a link under the Login button on react-admin's login page so that I can take the user through the account recovery process.
I have everything in place -- custom routes, custom components, API support for server-side checks and operations, the works. I just need to add that one link component on the login page to integrate the account recovery infrastructure with the rest of the site.
I have been googling for possible solutions and have found a few questions people asked in the past, but most of them were dealing with custom routes etc. and they did not really seem to be related to my issue. I have also looked at the official docs here, but they only talk about changing the background image on the login page.
Has anybody dealt with and solved this problem?
I am using react-admin 3.5.0.
Customizing the login page/form is often not attempted because the react-admin team made it easy to just "adopt" that login page (template) into any app set-up. Thanks, guys!!
Ok, not too fast. But what if I seriously want/need to customize the login page?
I met this challenge when I needed to refactor the login fields.
Let's take a closer look at how the <Login> is rendered:
First, you actually need to pass the loginPage prop to the <Admin/>;
<Admin loginPage={CustomLoginPage} />
Then, within the CustomLoginPage, render the form and include any other relevant info (in this case, your "forgot password" link)
import { Form } from 'react-final-form';
const CustomLoginPage = props => {
// any other logic
return (
<div>
<Form {...props} render={() => (<form>...</form>)} />
<a href='...'>Forgot Password?</a>
</div>
)
};
This code for the react-admin demo login-page will help you understand that last part further.

Stay on the edit page if get server side error

I am now using the react-admin framework, when the user clicks the Save button on the Edit page. Normally it will go to the List page and show an undo notification at the bottom, but at that time server-side gets validation error (for example, image size, file size). Then all user input at the Edit page is lost.
How can we still remain on the Edit page in case of the server-side error, and go to the List page only if the sever-side returns success?
If I put redirect = false, it will not go to the List page even if the server-side returns success:
const CustomToolbar = props => (
<Toolbar {props} >
<SaveButton redirect={false}/>
</Toolbar>
)
React Admin uses an approach called Optimistic Rendering: when a user fill a form, we are optimistic and render the better result.
This globally improve the user experience by making the results displayed faster, even before the API is reached.
The bad side is that, if the form isn't strictly validated client-side and the API throws an error, the user have to do it again.
From here, I see two solutions to your problem:
Implement a more strict client-side validation of your form
Disable the optimistic rendering by specifying undoable={false}
<Edit {...props} undoable={false}>
{...}
</Edit>

how to remove link to resource list view from menu?

I'm currently building out an application that has a boatload of resources that i will need list views of but don't want links to the list views in the menu. Is there a way to have access to them without having links on the side? to create the list i'm doing the following.
<resources
list={EmployeeList}
/>
docs don't mention this so any help would be appreciated.
I have say ~45 resources that i will need to access list views but only 6 or so are major enough to be accessed from the main menu. i'd still want access to them by viewing details of the other lists or show pages.
I'm no sure how or where you need to access these resources, but this is what I've done with some "lesser" resources I don't need to have the "List" view or sidebar link to:
Define
<Resource name="myresource" />
in App.js. Now you can make a list for example inside another resource's "show" view by using <ReferenceManyField resource="myresource" />

branch.io no longer auto-redirects with a custom deepview

We're creating a link through the branch.io API using the following data attributes:
$desktop_url, token, and $og_image_url.
When we open up the URL on an iOS device it loads a branch.io default deep view and automatically initiates the redirect to the app store.
When we clone the "Branch Default Passive Template" to create our own template, then proceed with the same steps above, it no longer initiates the automatic redirect to the app store.
Disabling the deep views restores the previous behavior.
I've tried passing configuring $ios_passive_deepview with our custom deepview and we get the same non-auto-redirect behavior.
What can we do to restore this auto-redirect behavior with a custom deep view?
(Also, when we provide an invalid path to our custom branch.io domain we get a redirect without any deep view, just a blank page -- not sure how to prevent that).
I resolved this by disabling the deep views in the dashboard and then passing in the deep view id into the "$ios_passive_deepview" in the create link api
It appears Branch adds this HTML to the bottom of their pages that auto-redirect. So you can have the same effect by adding it yourself.
<script type="text/javascript">window.onload = function() {window.top.location = "{{action}}";};</script>