skyouc
2025-04-14 23e63904e4c2b734f92bdfd5aac0e16948af72b3
rsf-admin/src/layout/MyMenu.jsx
@@ -1,168 +1,176 @@
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', minWidth: '24px' } }}
            />
          );
        }
      }
    });
  };
    }, [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 [];
};