Layout.tsx 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. import GlobalEffect from './GlobalEffect';
  2. import Header from './Header';
  3. import { makeStyles, Theme, createStyles } from '@material-ui/core';
  4. import NavMenu from '../menu/NavMenu';
  5. import { NavMenuItem } from '../menu/Types';
  6. import { useContext, useMemo } from 'react';
  7. import icons from '../icons/Icons';
  8. import { useTranslation } from 'react-i18next';
  9. import { useHistory, useLocation } from 'react-router-dom';
  10. import { authContext } from '../../context/Auth';
  11. import { IconsType } from '../icons/Types';
  12. import loadable from '@loadable/component';
  13. const PLUGIN_DEV = process.env?.REACT_APP_PLUGIN_DEV;
  14. const useStyles = makeStyles((theme: Theme) =>
  15. createStyles({
  16. root: {
  17. minHeight: '100vh',
  18. backgroundColor: '#f5f5f5',
  19. },
  20. content: {
  21. display: 'flex',
  22. '& .normalSearchIcon': {
  23. '& path': {
  24. fill: theme.palette.milvusGrey.dark,
  25. },
  26. },
  27. '& .activeSearchIcon': {
  28. '& path': {
  29. fill: theme.palette.primary.main,
  30. },
  31. },
  32. },
  33. body: {
  34. flex: 1,
  35. display: 'flex',
  36. flexDirection: 'column',
  37. height: '100vh',
  38. overflowY: 'scroll',
  39. },
  40. })
  41. );
  42. const Layout = (props: any) => {
  43. const history = useHistory();
  44. const { isAuth } = useContext(authContext);
  45. const { t: navTrans } = useTranslation('nav');
  46. const classes = useStyles();
  47. const location = useLocation();
  48. const defaultActive = useMemo(() => {
  49. if (location.pathname.includes('collection')) {
  50. return navTrans('collection');
  51. }
  52. if (location.pathname.includes('search')) {
  53. return navTrans('search');
  54. }
  55. if (location.pathname.includes('system')) {
  56. return navTrans('system');
  57. }
  58. return navTrans('overview');
  59. }, [location, navTrans]);
  60. const menuItems: NavMenuItem[] = [
  61. {
  62. icon: icons.navOverview,
  63. label: navTrans('overview'),
  64. onClick: () => history.push('/'),
  65. },
  66. // {
  67. // icon: icons.navSystem,
  68. // label: navTrans('system'),
  69. // onClick: () => history.push('/system'),
  70. // },
  71. {
  72. icon: icons.navCollection,
  73. label: navTrans('collection'),
  74. onClick: () => history.push('/collections'),
  75. },
  76. // {
  77. // icon: icons.navSearch,
  78. // label: navTrans('search'),
  79. // onClick: () => history.push('/search'),
  80. // iconActiveClass: 'activeSearchIcon',
  81. // iconNormalClass: 'normalSearchIcon',
  82. // },
  83. ];
  84. function importAll(r: any, outOfRoot = false) {
  85. r.keys().forEach((key: any) => {
  86. const content = r(key);
  87. const pathName = content.client?.path;
  88. if (!pathName) return;
  89. const result: NavMenuItem = {
  90. icon: icons.navOverview,
  91. label: content.client?.label || 'PLGUIN',
  92. };
  93. result.onClick = () => history.push(`${pathName}`);
  94. const iconName: IconsType = content.client?.iconName;
  95. const iconEntry = content.client?.icon;
  96. const dirName = key.split('/config.json').shift().split('/')[1];
  97. // const fileEntry = content.client?.entry;
  98. if (iconName) {
  99. result.icon = icons[iconName];
  100. } else if (iconEntry) {
  101. const customIcon = outOfRoot
  102. ? loadable(() => import(`all_plugins/${dirName}/client/${iconEntry}`))
  103. : loadable(() => import(`../../plugins/${dirName}/${iconEntry}`));
  104. result.icon = customIcon;
  105. }
  106. content.client?.iconActiveClass &&
  107. (result.iconActiveClass = content.client?.iconActiveClass);
  108. content.client?.iconNormalClass &&
  109. (result.iconNormalClass = content.client?.iconNormalClass);
  110. menuItems.push(result);
  111. });
  112. }
  113. importAll(require.context('../../plugins', true, /config\.json$/));
  114. PLUGIN_DEV &&
  115. importAll(require.context('all_plugins/', true, /config\.json$/), true);
  116. return (
  117. <div className={classes.root}>
  118. <GlobalEffect>
  119. <div className={classes.content}>
  120. {isAuth && (
  121. <NavMenu
  122. width="200px"
  123. data={menuItems}
  124. defaultActive={defaultActive}
  125. // used for nested child menu
  126. defaultOpen={{ [navTrans('overview')]: true }}
  127. />
  128. )}
  129. <div className={classes.body}>
  130. {isAuth && <Header />}
  131. {props.children}
  132. </div>
  133. </div>
  134. </GlobalEffect>
  135. </div>
  136. );
  137. };
  138. export default Layout;