admin-on-rest toggle menu (show / hide) - reactjs

I'm using admin-on-rest in my react application as admin interface.
My problem is the menu, I'm add a DashboardMenuItem to toggle (show/hide) the menu. But I have no idea what the onClick function should look like and I find no example of this in the documentary or somewhere else.
Can anyone help me by giving an example for this?
My Code:
const Menu = ({ hasDashboard, onMenuTap, resources, translate, logout }) => (
<div style={styles.main}>
<WithPermission value='ROLE_SA'>
{hasDashboard && <DashboardMenuItem onClick={onMenuTap} />}
</WithPermission>
{resources
.filter(r => r.list)
.map(resource => (
<MenuItemLink
key={resource.name}
to={`/${resource.name}`}
primaryText={translatedResourceName(resource, translate)}
leftIcon={<resource.icon />}
onClick={onMenuTap}
/>
))}
{/* <MenuItemLink primaryText='Reports' key='reports' to={`/reports`} leftIcon={<UserIcon />} onClick={onMenuTap} /> */}
<WithPermission value='ROLE_SA'>
<SelectField floatingLabelText='Language for Datasets' onChange={LocaleSwitcher}>
<MenuItem value={'de'} primaryText='DE' />
<MenuItem value={'en'} primaryText='EN' />
</SelectField>
</WithPermission>
{logout}
<img src={Logo} style={{maxWidth: '100%', margin: '0 auto'}} />
</div>
)

Related

antd collapse.panel not re rendering

I have this collapse panel in antd.
<Collapse defaultActiveKey={[1]} onChange={onChange}>
<Panel header="Billing Details" key="2" forceRender>
<BillingPanel
invoiceCycleOptions={invoiceCycleOptions}
projectData={projectData}
payModelOptions={payModelOptions}
accTypeOptions={accTypeOptions}
onDateChange={onDateChange}
isEditMode={isEditMode}
isPopulated={isPopulated}
prjStartDate={prjStartDate}
/>
</Panel>
<Panel header="Other Details" key="3" forceRender>
<OtherDetailsPanel
csmOptions={csmOptions}
projectData={projectData}
csm={csm}
onPrimaryCsmSelect={onPrimaryCsmSelect}
accountantOptions={accountantOptions?.map(
(option) => option?.name
)}
isEditMode={isEditMode}
secondaryCsmoptions={secondaryCsmoptions}
setShow={setShow}
setDocument={setDocument}
show={show}
salesPersonOptions={salesPersonOptions}
setIsValidSize={setIsValidSize}
isValidSize={isValidSize}
leadSourceOptions={leadSourceOptions}
marketingChannelOptions={marketingChannelOptions}
activeBillingOptions={activeBillingOptions}
activeBilling={activeBilling}
form={form}
selectedCsm={selectedCsm}
primaryCsm={primaryCsm}
secondaryCsmList={secondaryCsmList}
/>
</Panel>
</Collapse>
when projectData changes, the panel with the header "Other Details" does not re render. I am getting updated projectData in this component but not in the OtherDetailsPanel component. Can anyone help me?

How to use custom isOpen with a chakra component

I am relatively new to react and not sure why isOpen is not working as expected.
Please see the code below for the example that I am working with
I have a menu icon that is using isOpen to open navlinks:
const { isOpen, onOpen, onClose } = useDisclosure();
<IconButton variant={"unstyled"} bgColor={"white"} color={"black"} size={"s"} icon={isOpen ? <Hamburger size={"24"} /> : <Hamburger size={"24"} />} aria-label={"Open Menu"} display={{ md: "none" }} onClick={isOpen ? onClose : onOpen} />
{isOpen ? (
<Box color={"#b8860b"} pb={4} display={{ md: "none" }}>
<Stack as={"nav"} spacing={5}>
{Links.map(link => (
<Link key={link.name} href={link.route}>
<Flex paddingBottom="40px" h="40px" borderBottom="1px" borderColor="black" justifyContent={'left'}>
<Flex paddingLeft={"10px"} paddingTop={"3%"}> {link.icon}</Flex>
<Text p={2} color={"black"} >
{link.name}
</Text>
</Flex>
</Link>
))}
</Stack>
</Box>
) : null}
When I try using a custom isOpen to open a drawer component, i just cant get it to work..
What am I doing wrong?:
const { isOpenMenu, onOpenMenu, onCloseMenu } = useDisclosure()
<Button
bgColor={"white"}
onClick={isOpenMenu}
>
<BsCart4 size={"26px"} color={"black"} />
{cartItemCount > 0 && <Badge ml='1' fontSize='0.9em' colorScheme='green'>{cartItemCount}</Badge>}
</Button>
<Drawer
isOpen={isOpenMenu}
placement='right'
onClose={onCloseMenu}
finalFocusRef={btnRef}
>
<DrawerOverlay />
<DrawerContent>
<DrawerCloseButton />
<DrawerHeader>Create your account</DrawerHeader>
<DrawerBody>
<Input placeholder='Type here...' />
</DrawerBody>
<DrawerFooter>
<Button variant='outline' mr={3} onClick={onCloseMenu}>
Cancel
</Button>
<Button colorScheme='blue'>Save</Button>
</DrawerFooter>
</DrawerContent>
</Drawer>
```
When I use isOpen for the drawer it works fine so I thought having another isOpen but custom would open the drawer but its not working as expected.
Can someone help understand why my thinking isnt right based on how to use isOpen correctly?
It seems like only isOpen works when I switch it from using the menu bar and drawer
First of all, if you want to use custom names to the useDisclosure states, you have to set them like this:
const { isOpen: isOpenMenu, onOpen: onOpenMenu, onClose: onCloseMenu } = useDisclosure()
Also, the onClose prop of the drawer component is just a event handler, dont put your onCloseMenu function ther, just call it when you want to close the drawer, as you made on the cancel button, example:
<Button onClick={onCloseMenu} ... />

animation routes with framer motion

Hi i try to animate 2 routes form opacity 1 to 0 on exit. But for some reason on <Link> click the routes will change(ex. '/' => '/chat?name=bob&room=here') but the page content stay the same and it wont render the component of that specific route. Also the animation is working great once i use the "Go back button" from browser.
Anyone have idea why is not working on button click?
App.js
return (
<div>
<Router>
<AnimatePresence exitBeforeEnter>
<Switch location={location} key={location.key}>
<Route path="/" exact component={Login}></Route>
<Route path="/chat" component={ChatRoom}></Route>
</Switch>
</AnimatePresence>
</Router>
</div>
);
Login.js
return (
<motion.div
initial="out"
animate="in"
exit="out"
variants={pageTransition}
className="Login-Container"
>
//same code
<Link
onClick={(event) => (!name || !room ? event.preventDefault() : null)}
to={`/chat?name=${name}&room=${room}`}
>
<button
type="submit"
className="Login-Button"
>
Sign In
</button>
</Link>
</motion.div>
);
ChatRoom.js
return (
<motion.div
initial="out"
animate="in"
exit="out"
variants={pageTransition}
className="ChatRoom-Container"
>
<div className="ChatRoom-NavBar">
<NavLink to="/">
<div
className="ChatRoom-BackButton"
style={{ backgroundImage: `url(${arrow})` }}
></div>
</NavLink>
</div>
</motion.div>
);
};
Your initial and exit prop on motion.div seem to be using the same key i.e "out" try giving the exit prop a different key. Dont forget to adjust your variants as well when you make the change.

How to correctly add the Aside component to create a modal style button on the right side of my show page?

I am building a custom show page for an individual customer. Within this page I need a button that allows me to edit their points value they have. I am wanting to use the aside component that is built in react-admin but I can't seem to get it to work correctly.
I have followed the documentation to add the code for the aside component and I placed my button component within it. However it's not rendering to the page at all. I am receiving a TypeError. 'TypeError: Cannot read roperty "search" of undefined.'
const Aside = (...props) => {
const { customer_id: customer_id_string } = parse(props.location.search);
const customer_id = customer_id_string ? parseInt(customer_id_string, 10) : '';
return (
<div style={{ width: 200, margin: '1em'}}>
<Button
defaultValue={{ customer_id }}
redirect="show"
component={Link}
to={{
pathname: '/points/{{point-id}}/create',
}}
label="Add Points"
>
<Reward>Add Points</Reward>
</Button>
)
</div>
)
};
const CustomerShow = ({ classes, record, ...props }) => (
<Show aside={<Aside />} {...props}>
<TabbedShowLayout>
<Tab label="Customer Basics">
<TextField source="firstName" /><TextField source="lastName" />
<TextField source="email" />
<BooleanField source="active" />
</Tab>
<Tab label="The Rest">
<NumberField label="Points" source="points" />
<NumberField source="usedPoints" />
<NumberField source="expiredPoints" />
<NumberField source="lockedPoints" />
<BooleanField source="agreement1" />
<BooleanField source="agreement2" />
</Tab>
<Tab label="Transactions" resource="transactions" >
<ReferenceManyField
addLabel={false}
reference="transactions"
target="customerId"
pagination={<Pagination />}
perPage={10}
sort={{ field: 'createdAt', order: 'DESC' }}
><Datagrid rowClick="show" >
<DateField source="createdAt"/>
<TextField source="documentNumber"/>
<TextField source="documentType"/>
<NumberField source="grossValue"/>
<NumberField source="pointsEarned"/>
<NumberField source="pointsUsed"/>
</Datagrid>
</ReferenceManyField>
</Tab>
<Tab label="Points" resource="Points" >
<ReferenceManyField
addLabel={false}
reference="points"
target="customerId"
pagination={<Pagination />}
perPage={10}
sort={{ field: 'createdAt', order: 'DESC' }}
><Datagrid rowClick="show" >
<NumberField source="valueLocked" />
<NumberField source="valueUsed" />
<NumberField source="valueRemain" />
<NumberField source="valueExpired" />
<NumberField source="valueEarned" />
</Datagrid>
</ReferenceManyField>
</Tab>
</TabbedShowLayout>
</Show>
);
The expected results are a button on the right side of the page displaying the words "Add Points". The actual results are either a TypeError or the page renders but no button.
I figured out what I was doing wrong. I didn't have one of my sources filled out correctly. It was referencing the wrong source.

React-router4 display the name in component

I use react-router4 and try to display the name of the corresponding label in the commented location. I don't know how to solve this problem.
Does the react-router4 offer a solution to this problem? Can anyone show me how to do it?
Navigation.js:
...
<NavigationButton to="/" label="Dashboard" exact>
<MenuItem className={classes.menuItem}
selected={this.state.selected === "Dashboard"}
onClick={() => {this.setState({selected: "Dashboard"})}}>
<ListItemIcon className={classes.icon}>
<Home/>
</ListItemIcon>
<ListItemText classes={{primary: classes.primary}} inset primary="Dashboard"/>
</MenuItem>
</NavigationButton>
<NavigationButton to="/payment" label="Payment" exact>
<MenuItem className={classes.menuItem}
selected={this.state.selected === "Payment"}
onClick={() => {this.setState({selected: "Payment"})}}>
<ListItemIcon className={classes.icon}>
<Payment/>
</ListItemIcon>
<ListItemText classes={{primary: classes.primary}} inset primary="Moje płatności"/>
</MenuItem>
</NavigationButton>
...
Header:
...
<div className={classes.root}>
<div className={classes.appFrame}>
<AppBar
className={classNames(classes.appBar, {
[classes.appBarShift]: open,
[classes[`appBarShift-left`]]: open,
})}
>
<Toolbar disableGutters={!open} className={classes.toolBar}>
<IconButton
color="inherit"
aria-label="Open drawer"
onClick={this.handleDrawerToggle}
className={classNames(classes.menuButton, open)}
>
<MenuIcon />
</IconButton>
<Typography variant="h6" color="inherit" noWrap>
{/* print "Dashboard" when I choose Dashboard, or print "Payment" when I choose payment in Navigation.js. */}
</Typography>
</Toolbar>
</AppBar>
{before}
<main
className={classNames(classes.content, classes[`content-left`], {
[classes.contentShift]: open,
[classes[`contentShift-left`]]: open,
})}
>
<div className={classes.drawerHeader} />
<Switch>
<Route exact path="/" component={DashboardComponent} />
<Route exact path="/payment" component={PaymentComponent} />
<Redirect to="/" />
</Switch>
</main>
</div>
</div>
...
I use react-router4 and try to display the name of the corresponding label in the commented location. I don't know how to solve this problem.
Does the react-router4 offer a solution to this problem? Can anyone show me how to do it?
The approach is not right to display label of current component name with react-router as this will be an issue when it's a default export without even having a name. So it would be better to maintain a const LABEL = { ... } // all label with pathname as keys
So you can match this.props.location.pathname with your LABEL const object to display it properly.
const LABEL = {
dashboard : 'Dashboard',
home: 'Home'
}
in you render:
<Typography variant="h6" color="inherit" noWrap>
{LABEL[this.props.location.pathname]}
</Typography>
I hope this would help, Ask any questions if it doesn't help

Resources