Layout.tsx 4.4 KB

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