Browse Source

support custom icon and title

czhen 3 years ago
parent
commit
237734ae73

+ 11 - 3
client/src/components/layout/Layout.tsx

@@ -9,6 +9,7 @@ import { useTranslation } from 'react-i18next';
 import { useHistory, useLocation } from 'react-router-dom';
 import { authContext } from '../../context/Auth';
 import { IconsType } from '../icons/Types';
+import loadable from '@loadable/component';
 
 const PLUGIN_DEV = process.env?.REACT_APP_PLUGIN_DEV;
 
@@ -90,7 +91,7 @@ const Layout = (props: any) => {
     },
   ];
 
-  function importAll(r: any) {
+  function importAll(r: any, outOfRoot = false) {
     r.keys().forEach((key: any) => {
       const content = r(key);
       const pathName = content.client?.path;
@@ -101,9 +102,16 @@ const Layout = (props: any) => {
       };
       result.onClick = () => history.push(`${pathName}`);
       const iconName: IconsType = content.client?.iconName;
+      const iconEntry = content.client?.icon;
+      const dirName = key.split('/config.json').shift().split('/')[1];
+      // const fileEntry = content.client?.entry;
       if (iconName) {
-        // TODO: support custom icon
         result.icon = icons[iconName];
+      } else if (iconEntry) {
+        const customIcon = outOfRoot
+          ? loadable(() => import(`all_plugins/${dirName}/client/${iconEntry}`))
+          : loadable(() => import(`../../plugins/${dirName}/${iconEntry}`));
+        result.icon = customIcon;
       }
       content.client?.iconActiveClass &&
         (result.iconActiveClass = content.client?.iconActiveClass);
@@ -114,7 +122,7 @@ const Layout = (props: any) => {
   }
   importAll(require.context('../../plugins', true, /config\.json$/));
   PLUGIN_DEV &&
-    importAll(require.context('all_plugins/', true, /config\.json$/));
+    importAll(require.context('all_plugins/', true, /config\.json$/), true);
 
   return (
     <div className={classes.root}>

+ 6 - 3
client/src/components/menu/Types.ts

@@ -1,5 +1,6 @@
 import { ButtonProps } from '@material-ui/core/Button';
 import { ReactElement } from 'react';
+import { LoadableClassComponent } from '@loadable/component';
 
 export type SimpleMenuType = {
   label: string;
@@ -14,10 +15,12 @@ export type SimpleMenuType = {
   menuItemWidth?: string;
 };
 
+type CustomIcon = (
+  props?: any
+) => React.ReactElement<any, string | React.JSXElementConstructor<any>>;
+
 export type NavMenuItem = {
-  icon: (
-    props?: any
-  ) => React.ReactElement<any, string | React.JSXElementConstructor<any>>;
+  icon: CustomIcon | LoadableClassComponent<any>;
   iconActiveClass?: string;
   iconNormalClass?: string;
   label: string;

+ 14 - 3
client/src/hooks/Navigation.ts

@@ -6,12 +6,15 @@ import { ALL_ROUTER_TYPES, NavInfo } from '../router/Types';
 export const useNavigationHook = (
   type: ALL_ROUTER_TYPES,
   extraParam?: {
-    collectionName: string;
+    collectionName?: string;
+    title?: string;
   }
 ) => {
   const { t: navTrans } = useTranslation('nav');
   const { setNavInfo } = useContext(navContext);
-  const { collectionName } = extraParam || { collectionName: '' };
+  const { collectionName = '', title = 'PLUGIN TITLE' } = extraParam || {
+    collectionName: '',
+  };
 
   useEffect(() => {
     switch (type) {
@@ -55,8 +58,16 @@ export const useNavigationHook = (
         setNavInfo(navInfo);
         break;
       }
+      case ALL_ROUTER_TYPES.PLUGIN: {
+        const navInfo: NavInfo = {
+          navTitle: title,
+          backPath: '',
+        };
+        setNavInfo(navInfo);
+        break;
+      }
       default:
         break;
     }
-  }, [type, navTrans, setNavInfo, collectionName]);
+  }, [type, navTrans, setNavInfo, collectionName, title]);
 };

+ 3 - 1
client/src/router/Types.ts

@@ -8,7 +8,9 @@ export enum ALL_ROUTER_TYPES {
   // 'search'
   SEARCH = 'search',
   // 'system'
-  SYSTEM = 'system'
+  SYSTEM = 'system',
+  // plugins
+  PLUGIN = 'plugin',
 }
 
 export type NavInfo = {