How to configure the resource and crud operation programmatic according to the user permission on react-admin - resources

I was using react-admin, it's really quickly and productively. However, I want to implement some features like programmatic display resource and crud operation component according to the attributes of a logged user.
Something like this.
const App = () => (
<Admin restClient={jsonServerRestClient('http://jsonplaceholder.typicode.com')}>
<Resource name="users" list={UserList} haveListPermission={user.hasUsersListPermission}/>
<Resource name="tags" havePermission={user.hasTagPermission} />
</Admin>
);

This is documented here: https://marmelab.com/react-admin/Authorization.html
In a nutshell, the Admin component accepts a function as children (think render prop) which will be called with your permissions (from your authProvider). So assuming you are using react-admin (and not admin-on-rest) and your authProvider resolves with the current user when called with type AUTH_GET_PERMISSIONS:
const App = () => (
<Admin authProvider={authProvider} dataProvider={jsonServerRestClient('http://jsonplaceholder.typicode.com')}>
{user => (
{user.hasUsersListPermission && <Resource name="users" list={UserList} />}
{user.hasTagPermission && <Resource name="tags" />
)}
)}
</Admin>
);

Related

How do I avoid visual bug when navigating from one screen to another? - React Native Expo

I'm creating a sign in screen and a create account screen on my application. I have buttons that go back and forth to each other. Both screens work fine individually. When I do this, there can often be a visual error like so:
My App.js Code:
const App = () => {
return (
<NavigationContainer theme={theme}>
<Stack.Navigator screenOptions={{ headerShown: false}} initialRouteName="CreateAccountScreen">
<Stack.Screen name ="CreateAccountScreen" component={CreateAccountScreen} />
<Stack.Screen name ="SignInScreen" component={ SignInScreen } />
</Stack.Navigator>
</NavigationContainer>
);
}
Code from each Screens button that goes back and forth:
onSignUpButtonPressed = () => {
navigation.navigate("SignInScreen")
}
onCreateAccountButtonPressed = () => {
navigation.navigate("CreateAccountScreen")
}
Displays seem to overlay themselves in a bad way
I've tried a bunch of things and this has happened on several screens...
Your initialRouteName is set up as we can see but on your Stack.Screen you also give it the Component attribute.
I did a test based on how my navigation looks and I did not get the visual bug you showed so I think if you removed the component attribute and maybe just put the component tag inside your Stack.Screen as shown below it might work. Just imagine my Home is your CreateAccountScreen.
<Stack.Navigator
initialRouteName='Home'
>
<Stack.Screen
name="Home"
options={{
headerShown: false,
}}
>
{props => <Home {...props} username='Bella' />}
</Stack.Screen>
You also dont have the code in your question to define Stack like this:
const Stack = createStackNavigator();

Use a Username in a Path to Route a Component (React-router-dom)

I am having a hard time setting up my react-router so that when the path matches the user's username, the userProfile component will be routed and show individually. For example, when the URL is http://localhost:3000/myusername, the userProfile component will only show. I'm kind of confused on how it will work if someone just pastes the entire link instead of being directed to someone's page through the UI.
<Switch>
<Route path="/" component={userProfile} />
<PrivateRoute exact path="/test2" component={test2} />
<PrivateRoute exact path="/test3" component={test3} />
</Switch>
Any help would be appreciated!
You can use this method and access to username in test3 component and handle getting data and showing this page
<Switch>
<Route path="/" component={userProfile} />
<PrivateRoute exact path="/test2" component={test2} />
<PrivateRoute exact path="/:username" component={test3} />
</Switch>
I found that if you just use /:id in the path, then the path extension will pass automatically down to the userProfile component when you use the const {id} = useParams() function in the userProfile component. Then I passed the _id down as a prop from the userProfile component to the Info component so that it can be used to automatically fetch data in a useEffect() and redux dispatch() function. Oh and also, the <Route path="/:id" component={userProfile} /> needs to be an exact path and must go to the bottom of the Route Switch list so that it doesn't get picked first.
<Switch>
<PrivateRoute exact path="/test2" component={test2} />
<PrivateRoute exact path="/test3" component={test3} />
<Route exact path="/:id" component={userProfile} />
</Switch>
const Profile = () => {
const { id } = useParams();
return (
<div>
<Info _id={id} />
</div>
);
};
export default Profile;
const Info = (props) => {
const dispatch = useDispatch();
useEffect(() => {
dispatch(getProfileInfo(props._id));
}, []);
return (
<div></div>
);
};
export default Info;

Showcase view on first launch of react native app

I have been looking for a guide to create a showcase view on first launch of my react native app, I might don't know the correct word for it, actually it's a user guide for features on first launch, it has a direction towards the icon and it's details, I haven't found anything on it, it'll be a great help if anyone guide me about that, thanks
Here is some demo code from the doc of react-navigation. I think it's similar to your case.
if (state.isLoading) {
// We haven't finished checking for the token yet
return <SplashScreen />;
}
return (
<Stack.Navigator>
{state.userToken == null ? (
// No token found, user isn't signed in
<Stack.Screen
name="SignIn"
component={SignInScreen}
options={{
title: 'Sign in',
// When logging out, a pop animation feels intuitive
// You can remove this if you want the default 'push' animation
animationTypeForReplace: state.isSignout ? 'pop' : 'push',
}}
/>
) : (
// User is signed in
<Stack.Screen name="Home" component={HomeScreen} />
)}
</Stack.Navigator>
);
Add a firstLaunch state to true first and then set it to false and save in the asyncstorage.Something like:
let firstLauch = await AsyncStorage.getItem("firstLauch");
firstLauch = JSON.parse(firstLauch);
firstLauch = firstLauch === false?firstLauch:true
let [isFirstLauch,setIsFirstLauch]=useState(firstLauch);
return (
<Stack.Navigator>
{isFirstLauch ? (
// No token found, user isn't signed in
<Stack.Screen
name="FirstLauch"
component={FirstLauchScreen}
/>
) : (
<Stack.Screen name="Home" component={HomeScreen} />
)}
</Stack.Navigator>
);
Don't forget to set firstLauch to false in your firstLauchScreen.
Have a try with the popular npm package for creating your showcase of first launch https://www.npmjs.com/package/react-native-copilot

How do I create/edit a user profile for a Stream react-native app?

Is there a builtin UI component in the Stream for react-native library to edit a user's profile?
I have the feeds and activities working and integrated with my user id and token server side api, but users obviously show up as the default "Unknown" with no photo. I don't have profile storage yet in this new application so I'm wondering if there is a quick drop-in for a Profile screen and editing of that profile or if I have to build that and add the metadata to the stream User API.
There is no profile component, but you can access the information and create your own.
Firstly, set the profileImage field of the user in getstream like so (example shown server side but you can use do client side with a token):
const client = stream.connect('xxx', 'xxxxxxxxxxxxxx', 'xxxxxx');
let clientData = await client.user(userId).get();
if (!clientData.data) return null;
clientData.data.profileImage = 'https://cdn.com/profile.png';
await client.user(context.params.userId).update(clientData.data);
Then you can access it like so on client: (example shows feed with a custom header.):
const CustomActivity = (props) => {
return <Activity {...props}
Header={
<View style={styles.avatarView}>
<Avatar
source={props.activity.actor.data.profileImage}
size={36}
noShadow
/>
<View style={styles.actorView}>
<Text style={styles.actorName}>{props.activity.actor.data.name}</Text>
<Text style={styles.metaData}>{formatRelative(new Date(props.activity.time), new Date())}</Text>
</View>
</View>
}>
</Activity>
<StreamApp apiKey={STREAM_API_KEY} appId={STREAM_APP_ID} token={user.activity.token}>
<FlatFeed feedGroup="timeline" notify Activity={CustomActivity} />
</StreamApp>

Protect routes in react with server side rendering

I have a react app and I serving it with Node js. I currently have a jwt token implemented in node js. So, when I login a token is sent back to the client and then stored in localstorage.
To verify that the user is logged in and has rights to access some of the pages. I will need to
Get the token from local storage
Check the expiry of the token. And if it is expired redirect them back to the login page.
I currently cannot get passed the 1st step
Here is what I have
private-route.js
function PrivateRoute({ component: Component, ...rest }) {
const [token, setToken] = useState();
useEffect(() => {
setToken(localStorage.getItem("usr-sess"));
console.log(token);
}, [token]);
return (
<Route
{...rest}
render={props =>
token ? (
<Component {...props} />
) : (
<Redirect to="/login" />
)
}
/>
);
}
export default PrivateRoute;
app.js
<Switch>
<Route exact path="/login" component={LoadableLogin} />
<PrivateRoute eexact path="/test" component={LoadableTestPage} />
<Route component={LoadableNotFound} />
</Switch>
server.tsx
const jsx = renderToString(
<ApolloProvider client={clientConfig}>
<Loadable.Capture report={moduleName => modules.push(moduleName)}>
<StaticRouter context={context} location={req.url}>
<App />
</StaticRouter>
</Loadable.Capture>
</ApolloProvider>
);
I constantly keep being redirected back to login even when the token is there.
The issue is that it takes a bit of time to setToken() and by then it will redirect me back to login. Is there any way to do this?
Not using useEffect and doing
localStorage.getItem("usr-sess") ? (
<Component {...props} />
) : (
<Redirect to="/login" />
)
throws a localStorage undefined error, I can't think of anything else to do.

Resources