feat(ui): Support route types in plugin system

This commit is contained in:
robin
2024-04-08 17:44:08 +08:00
committed by dashuai
parent d91cb2e60f
commit 1ce7863376
3 changed files with 56 additions and 23 deletions
+3 -1
View File
@@ -21,6 +21,7 @@ import { Suspense, lazy } from 'react';
import { RouteObject } from 'react-router-dom';
import Layout from '@/pages/Layout';
import { mergeRoutePlugins } from '@/utils/pluginKit';
import baseRoutes, { RouteNode } from './routes';
import RouteGuard from './RouteGuard';
@@ -69,5 +70,6 @@ const routeWrapper = (routeNodes: RouteNode[], root: RouteNode[]) => {
};
routeWrapper(baseRoutes, routes);
const mergedRoutes = mergeRoutePlugins(routes);
export default routes as RouteObject[];
export default mergedRoutes as RouteObject[];
+46 -21
View File
@@ -17,14 +17,16 @@
* under the License.
*/
import { NamedExoticComponent, FC } from 'react';
import React from 'react';
import builtin from '@/plugins/builtin';
import * as allPlugins from '@/plugins';
import type * as Type from '@/common/interface';
import { LOGGED_TOKEN_STORAGE_KEY } from '@/common/constants';
import { getPluginsStatus } from '@/services';
import Storage from '@/utils/storage';
import { initI18nResource } from './utils';
import { initI18nResource, Plugin, PluginInfo, PluginType } from './utils';
/**
* This information is to be defined for all components.
@@ -38,24 +40,6 @@ import { initI18nResource } from './utils';
* @field description: Plugin description, optionally configurable. Usually read from the `i18n` file
*/
export type PluginType = 'connector' | 'search' | 'editor';
export interface PluginInfo {
slug_name: string;
type: PluginType;
name?: string;
description?: string;
}
export interface Plugin {
info: PluginInfo;
component: NamedExoticComponent | FC;
i18nConfig?;
hooks?: {
useRender?: Array<(element: HTMLElement | null) => void>;
};
activated?: boolean;
}
class Plugins {
plugins: Plugin[] = [];
@@ -155,5 +139,46 @@ const useRenderHtmlPlugin = (element: HTMLElement | null) => {
});
};
export { useRenderHtmlPlugin };
const getRoutePlugins = () => {
return plugins.getPlugins().filter((plugin) => plugin.info.type === 'route');
};
const defaultProps = () => {
const token = Storage.get(LOGGED_TOKEN_STORAGE_KEY) || '';
return {
key: token,
headers: {
Authorization: token,
},
};
};
const mergeRoutePlugins = (routes) => {
const routePlugins = getRoutePlugins();
if (routePlugins.length === 0) {
return routes;
}
routes.forEach((route) => {
if (route.page === 'pages/Layout') {
route.children?.forEach((child) => {
if (child.page === 'pages/SideNavLayout') {
routePlugins.forEach((plugin) => {
const { slug_name, route: path } = plugin.info;
const Component = plugin.component;
child.children.push({
page: `plugin/${slug_name}`,
path,
element: React.createElement(Component, defaultProps(), null),
});
});
}
});
}
});
return routes;
};
export { useRenderHtmlPlugin, mergeRoutePlugins };
export type { Plugin, PluginInfo, PluginType };
export default plugins;
+7 -1
View File
@@ -35,17 +35,23 @@ import i18next from 'i18next';
const I18N_NS = 'plugin';
export type PluginType = 'connector' | 'search' | 'editor';
export type PluginType = 'connector' | 'search' | 'editor' | 'route';
export interface PluginInfo {
slug_name: string;
type: PluginType;
name?: string;
description?: string;
route?: string;
}
export interface Plugin {
info: PluginInfo;
component: NamedExoticComponent | FC;
i18nConfig?;
hooks?: {
useRender?: Array<(element: HTMLElement | null) => void>;
};
activated?: boolean;
}
interface I18nResource {