|  |  | 
 |  |  | import React, { useState, useEffect, useMemo, Suspense } from "react"; | 
 |  |  | import { | 
 |  |  |     useTranslate, | 
 |  |  |     DashboardMenuItem, | 
 |  |  |     MenuItemLink, | 
 |  |  |     Menu, | 
 |  |  |     useSidebarState, | 
 |  |  |     usePermissions, | 
 |  |  | } from 'react-admin'; | 
 |  |  | import { useLocation } from 'react-router-dom'; | 
 |  |  | import { Box } from '@mui/material'; | 
 |  |  | import SubMenu from './SubMenu'; | 
 |  |  | import SettingsIcon from '@mui/icons-material/Settings'; | 
 |  |  | import DashboardIcon from '@mui/icons-material/Dashboard'; | 
 |  |  | import HorizontalRuleIcon from '@mui/icons-material/HorizontalRule'; | 
 |  |  | import PersonIcon from '@mui/icons-material/Person'; | 
 |  |  | import * as Icons from '@mui/icons-material'; | 
 |  |  |   useTranslate, | 
 |  |  |   DashboardMenuItem, | 
 |  |  |   MenuItemLink, | 
 |  |  |   Menu, | 
 |  |  |   useSidebarState, | 
 |  |  |   usePermissions, | 
 |  |  | } from "react-admin"; | 
 |  |  | import { useLocation } from "react-router-dom"; | 
 |  |  | import { Box } from "@mui/material"; | 
 |  |  | import SubMenu from "./SubMenu"; | 
 |  |  | import SettingsIcon from "@mui/icons-material/Settings"; | 
 |  |  | import DashboardIcon from "@mui/icons-material/Dashboard"; | 
 |  |  | import HorizontalRuleIcon from "@mui/icons-material/HorizontalRule"; | 
 |  |  | import PersonIcon from "@mui/icons-material/Person"; | 
 |  |  | import * as Icons from "@mui/icons-material"; | 
 |  |  |  | 
 |  |  | const getIconComponent = (iconStr) => { | 
 |  |  |     return Icons[iconStr] || HorizontalRuleIcon; | 
 |  |  |   return Icons[iconStr] || HorizontalRuleIcon; | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | export const MyMenu = ({ dense = false }) => { | 
 |  |  |     const [state, setState] = useState({}); | 
 |  |  |     const translate = useTranslate(); | 
 |  |  |     const location = useLocation(); | 
 |  |  |     const [sidebarIsOpen] = useSidebarState(); | 
 |  |  |     const { isPending, permissions } = usePermissions(); | 
 |  |  |   const [state, setState] = useState({}); | 
 |  |  |   const translate = useTranslate(); | 
 |  |  |   const location = useLocation(); | 
 |  |  |   const [sidebarIsOpen] = useSidebarState(); | 
 |  |  |   const { isPending, permissions } = usePermissions(); | 
 |  |  |  | 
 |  |  |     useEffect(() => { | 
 |  |  |         // default open sub menu | 
 |  |  |         const defaultExpandMenu = ["menu.system", "menu.dispatcher", "menu.equipment"]; | 
 |  |  |         permissions?.forEach(item => { | 
 |  |  |             if (defaultExpandMenu.includes(item.name)) { | 
 |  |  |                 setState(state => ({ ...state, [item.route]: true })); | 
 |  |  |             } | 
 |  |  |         }); | 
 |  |  |     }, [permissions]); | 
 |  |  |   useEffect(() => { | 
 |  |  |     // default open sub menu | 
 |  |  |     const defaultExpandMenu = [ | 
 |  |  |       "menu.system", | 
 |  |  |       "menu.dispatcher", | 
 |  |  |       "menu.equipment", | 
 |  |  |     ]; | 
 |  |  |     permissions?.forEach((item) => { | 
 |  |  |       if (defaultExpandMenu.includes(item.name)) { | 
 |  |  |         setState((state) => ({ ...state, [item.route]: true })); | 
 |  |  |       } | 
 |  |  |     }); | 
 |  |  |   }, [permissions]); | 
 |  |  |  | 
 |  |  |     useEffect(() => { | 
 |  |  |         // expand this parent menu | 
 |  |  |         const currentPath = location.pathname; | 
 |  |  |         const parentRoutes = findParentRoutes(currentPath, permissions) | 
 |  |  |         for (const parentRoute of parentRoutes) { | 
 |  |  |             setState(state => ({ ...state, [parentRoute]: true })); | 
 |  |  |   useEffect(() => { | 
 |  |  |     // expand this parent menu | 
 |  |  |     const currentPath = location.pathname; | 
 |  |  |     const parentRoutes = findParentRoutes(currentPath, permissions); | 
 |  |  |     for (const parentRoute of parentRoutes) { | 
 |  |  |       setState((state) => ({ ...state, [parentRoute]: true })); | 
 |  |  |     } | 
 |  |  |   }, [location.pathname]); | 
 |  |  |  | 
 |  |  |   const handleToggle = (menu) => { | 
 |  |  |     setState((state) => ({ ...state, [menu]: !state[menu] })); | 
 |  |  |   }; | 
 |  |  |  | 
 |  |  |   const getIcon = (iconStr) => { | 
 |  |  |     const IconComponent = getIconComponent(iconStr); | 
 |  |  |     if (IconComponent) { | 
 |  |  |       return <IconComponent />; | 
 |  |  |     } else { | 
 |  |  |       return <KeyboardArrowDownIcon /> | 
 |  |  |     } | 
 |  |  |   }; | 
 |  |  |  | 
 |  |  |   const generateMenu = (permissions) => { | 
 |  |  |     return permissions.map((node) => { | 
 |  |  |       if (node.children) { | 
 |  |  |         return ( | 
 |  |  |           <SubMenu | 
 |  |  |             key={node.id} | 
 |  |  |             handleToggle={() => handleToggle(node.route)} | 
 |  |  |             isOpen={state[node.route]} | 
 |  |  |             name={node.name} | 
 |  |  |             dense={dense} | 
 |  |  |             icon={getIcon(node.icon)} | 
 |  |  |           > | 
 |  |  |             {generateMenu(node.children)} | 
 |  |  |           </SubMenu> | 
 |  |  |         ); | 
 |  |  |       } else { | 
 |  |  |         if (node.component) { | 
 |  |  |           return ( | 
 |  |  |             <MenuItemLink | 
 |  |  |               key={node.id} | 
 |  |  |               to={node.component} // correspond to Resource.name | 
 |  |  |               state={{ _scrollToTop: true }} | 
 |  |  |               // primaryText={translate(`resources.orders.name`, { | 
 |  |  |               //     smart_count: 2, | 
 |  |  |               // })} | 
 |  |  |               primaryText={node.name} | 
 |  |  |               leftIcon={getIcon(node.icon)} | 
 |  |  |               dense={dense} | 
 |  |  |               // sx={{ '& .RaMenuItemLink-icon': { visibility: 'hidden' } }} | 
 |  |  |             /> | 
 |  |  |           ); | 
 |  |  |         } | 
 |  |  |       } | 
 |  |  |     }); | 
 |  |  |   }; | 
 |  |  |  | 
 |  |  |     }, [location.pathname]); | 
 |  |  |  | 
 |  |  |     const handleToggle = (menu) => { | 
 |  |  |         setState(state => ({ ...state, [menu]: !state[menu] })); | 
 |  |  |     }; | 
 |  |  |  | 
 |  |  |     const getIcon = (iconStr) => { | 
 |  |  |         const IconComponent = getIconComponent(iconStr); | 
 |  |  |         if (IconComponent) { | 
 |  |  |             return <IconComponent />; | 
 |  |  |         } | 
 |  |  |     }; | 
 |  |  |  | 
 |  |  |     const generateMenu = (permissions) => { | 
 |  |  |         return permissions.map((node) => { | 
 |  |  |             if (node.children) { | 
 |  |  |                 return ( | 
 |  |  |                     <SubMenu | 
 |  |  |                         key={node.id} | 
 |  |  |                         handleToggle={() => handleToggle(node.route)} | 
 |  |  |                         isOpen={state[node.route]} | 
 |  |  |                         name={node.name} | 
 |  |  |                         dense={dense} | 
 |  |  |                         icon={getIcon(node.icon)} | 
 |  |  |                     > | 
 |  |  |                         {generateMenu(node.children)} | 
 |  |  |                     </SubMenu> | 
 |  |  |                 ); | 
 |  |  |             } else { | 
 |  |  |                 if (node.component) { | 
 |  |  |                     return ( | 
 |  |  |                         <MenuItemLink | 
 |  |  |                             key={node.id} | 
 |  |  |                             to={node.component} // correspond to Resource.name | 
 |  |  |                             state={{ _scrollToTop: true }} | 
 |  |  |                             // primaryText={translate(`resources.orders.name`, { | 
 |  |  |                             //     smart_count: 2, | 
 |  |  |                             // })} | 
 |  |  |                             primaryText={node.name} | 
 |  |  |                             leftIcon={getIcon(node.icon)} | 
 |  |  |                             dense={dense} | 
 |  |  |                         /> | 
 |  |  |                     ); | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |         }); | 
 |  |  |     }; | 
 |  |  |  | 
 |  |  |     return isPending | 
 |  |  |         ? (<div>Waiting for permissions...</div>) : | 
 |  |  |         ( | 
 |  |  |             <Box | 
 |  |  |                 sx={{ | 
 |  |  |                     width: sidebarIsOpen ? 200 : 50, | 
 |  |  |                     marginTop: 1, | 
 |  |  |                     marginBottom: 1, | 
 |  |  |                     transition: theme => | 
 |  |  |                         theme.transitions.create('width', { | 
 |  |  |                             easing: theme.transitions.easing.sharp, | 
 |  |  |                             duration: theme.transitions.duration.leavingScreen, | 
 |  |  |                         }), | 
 |  |  |                 }} | 
 |  |  |             > | 
 |  |  |                 <Menu.Item | 
 |  |  |                     to="/dashboard" | 
 |  |  |                     primaryText="menu.dashboard" | 
 |  |  |                     leftIcon={<DashboardIcon />} | 
 |  |  |                 /> | 
 |  |  |                 {permissions && (generateMenu(permissions))} | 
 |  |  |                 {/* <Menu.ResourceItems /> */} | 
 |  |  |                 <Menu.Item | 
 |  |  |                     to="/settings" | 
 |  |  |                     primaryText="menu.settings" | 
 |  |  |                     leftIcon={<PersonIcon />} | 
 |  |  |                 /> | 
 |  |  |             </Box> | 
 |  |  |         ) | 
 |  |  | } | 
 |  |  |   return isPending ? ( | 
 |  |  |     <div>Waiting for permissions...</div> | 
 |  |  |   ) : ( | 
 |  |  |     <Box | 
 |  |  |       sx={{ | 
 |  |  |         width: sidebarIsOpen ? 200 : 50, | 
 |  |  |         marginTop: 1, | 
 |  |  |         marginBottom: 1, | 
 |  |  |         transition: (theme) => | 
 |  |  |           theme.transitions.create("width", { | 
 |  |  |             easing: theme.transitions.easing.sharp, | 
 |  |  |             duration: theme.transitions.duration.leavingScreen, | 
 |  |  |           }), | 
 |  |  |       }} | 
 |  |  |     > | 
 |  |  |       <Menu.Item | 
 |  |  |         to="/dashboard" | 
 |  |  |         primaryText="menu.dashboard" | 
 |  |  |         leftIcon={<DashboardIcon />} | 
 |  |  |       /> | 
 |  |  |       {permissions && generateMenu(permissions)} | 
 |  |  |       {/* <Menu.ResourceItems /> */} | 
 |  |  |       <Menu.Item | 
 |  |  |         to="/settings" | 
 |  |  |         primaryText="menu.settings" | 
 |  |  |         leftIcon={<PersonIcon />} | 
 |  |  |       /> | 
 |  |  |     </Box> | 
 |  |  |   ); | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | const findParentRoutes = (pathname, permissions) => { | 
 |  |  |     if (!pathname || !permissions) { | 
 |  |  |         return []; | 
 |  |  |     } | 
 |  |  |     const findMenu = (currentPermissions, path) => { | 
 |  |  |         for (const item of currentPermissions) { | 
 |  |  |             if (item.component === path) { | 
 |  |  |                 return item; | 
 |  |  |             } | 
 |  |  |             if (item.children) { | 
 |  |  |                 const found = findMenu(item.children, path); | 
 |  |  |                 if (found) { | 
 |  |  |                     return found; | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |         return null; | 
 |  |  |     }; | 
 |  |  |  | 
 |  |  |     const findParentRoutesRecursive = (item, allPermissions) => { | 
 |  |  |         const parentRoutes = []; | 
 |  |  |         let current = item; | 
 |  |  |         while (current && current.parentId) { | 
 |  |  |             const parent = allPermissions.find(permission => permission.id === current.parentId); | 
 |  |  |             if (parent) { | 
 |  |  |                 parentRoutes.push(parent.route); | 
 |  |  |                 current = parent; | 
 |  |  |             } else { | 
 |  |  |                 break; | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         return parentRoutes; | 
 |  |  |     }; | 
 |  |  |  | 
 |  |  |     const currentMenu = findMenu(permissions, pathname.replace("/", "")); | 
 |  |  |     if (currentMenu) { | 
 |  |  |         return findParentRoutesRecursive(currentMenu, permissions); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |   if (!pathname || !permissions) { | 
 |  |  |     return []; | 
 |  |  | }; | 
 |  |  |   } | 
 |  |  |   const findMenu = (currentPermissions, path) => { | 
 |  |  |     for (const item of currentPermissions) { | 
 |  |  |       if (item.component === path) { | 
 |  |  |         return item; | 
 |  |  |       } | 
 |  |  |       if (item.children) { | 
 |  |  |         const found = findMenu(item.children, path); | 
 |  |  |         if (found) { | 
 |  |  |           return found; | 
 |  |  |         } | 
 |  |  |       } | 
 |  |  |     } | 
 |  |  |     return null; | 
 |  |  |   }; | 
 |  |  |  | 
 |  |  |   const findParentRoutesRecursive = (item, allPermissions) => { | 
 |  |  |     const parentRoutes = []; | 
 |  |  |     let current = item; | 
 |  |  |     while (current && current.parentId) { | 
 |  |  |       const parent = allPermissions.find( | 
 |  |  |         (permission) => permission.id === current.parentId, | 
 |  |  |       ); | 
 |  |  |       if (parent) { | 
 |  |  |         parentRoutes.push(parent.route); | 
 |  |  |         current = parent; | 
 |  |  |       } else { | 
 |  |  |         break; | 
 |  |  |       } | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     return parentRoutes; | 
 |  |  |   }; | 
 |  |  |  | 
 |  |  |   const currentMenu = findMenu(permissions, pathname.replace("/", "")); | 
 |  |  |   if (currentMenu) { | 
 |  |  |     return findParentRoutesRecursive(currentMenu, permissions); | 
 |  |  |   } | 
 |  |  |  | 
 |  |  |   return []; | 
 |  |  | }; |