nocobase/packages/core/client/src/pm/PluginSetting.tsx
jack zhang 35b06cbfa0
refactor: plugin settings manager (#2712)
* feat: add settingsCenter

* fix: style bug

* chore: optimized code

* refactor: settingCenter Auth

* feat: add aclSnippet option

* refactor: all plugin's setting center api

* feat: add plugin with name

* docs: add settings-center doc

* fix: settings center menu sort by name

* fix: change setting center layout

* fix: change hello sort

* test: add SettingsCenter.ts test case

* fix: bug

* fix: acl bug

* fix: bug

* fix: bug and 404 page

* fix: test bug

* fix: test bug

* fix: bug

* fix: locale

* fix: styling

* fix: rename settingsCenter to pluginSettingsManager

* fix: styling

* fix: e2e bug

* fix: e2e bug

* fix: locale

* feat: update docs

* fix: update

---------

Co-authored-by: chenos <chenlinxh@gmail.com>
2023-11-13 11:01:18 +08:00

158 lines
5.1 KiB
TypeScript

import { PageHeader } from '@ant-design/pro-layout';
import { css } from '@emotion/css';
import { Layout, Menu, Result } from 'antd';
import _, { get } from 'lodash';
import React, { createContext, useCallback, useMemo } from 'react';
import { Navigate, Outlet, useLocation, useNavigate } from 'react-router-dom';
import { useStyles } from './style';
import { ADMIN_SETTINGS_PATH, PluginSettingsPageType, useApp } from '../application';
import { useCompile } from '../schema-component';
export const SettingsCenterContext = createContext<any>({});
function getMenuItems(list: PluginSettingsPageType[]) {
return list.map((item) => {
return {
key: item.name,
label: item.label,
title: item.title,
icon: item.icon,
children: item.children?.length ? getMenuItems(item.children) : undefined,
};
});
}
export const SettingsCenterComponent = () => {
const { styles, theme } = useStyles();
const app = useApp();
const navigate = useNavigate();
const location = useLocation();
const compile = useCompile();
const settings = useMemo(() => {
const list = app.pluginSettingsManager.getList();
// compile title
function traverse(settings: PluginSettingsPageType[]) {
settings.forEach((item) => {
item.title = compile(item.title);
item.label = compile(item.title);
if (item.children?.length) {
traverse(item.children);
}
});
}
traverse(list);
return list;
}, [app.pluginSettingsManager, compile]);
const getFirstDeepChildPath = useCallback((settings: PluginSettingsPageType[]) => {
if (!settings || !settings.length) {
return '/admin';
}
const first = settings[0];
if (first.children?.length) {
return getFirstDeepChildPath(first.children);
}
return first.path;
}, []);
const settingsMapByPath = useMemo<Record<string, PluginSettingsPageType>>(() => {
const map = {};
const traverse = (settings: PluginSettingsPageType[]) => {
settings.forEach((item) => {
map[item.path] = item;
if (item.children?.length) {
traverse(item.children);
}
});
};
traverse(settings);
return map;
}, [settings]);
const currentSetting = useMemo(() => settingsMapByPath[location.pathname], [location.pathname, settingsMapByPath]);
const currentPlugin = useMemo(() => {
if (!currentSetting) {
return null;
}
return settings.find((item) => item.name === currentSetting.pluginName);
}, [currentSetting, settings]);
const sidebarMenus = useMemo(() => {
return getMenuItems(settings.map((item) => ({ ...item, children: null })));
}, [settings]);
if (!currentSetting || location.pathname === ADMIN_SETTINGS_PATH || location.pathname === ADMIN_SETTINGS_PATH + '/') {
return <Navigate replace to={getFirstDeepChildPath(settings)} />;
}
if (location.pathname === currentPlugin.path && currentPlugin.children?.length > 0) {
return <Navigate replace to={getFirstDeepChildPath(currentPlugin.children)} />;
}
return (
<div>
<Layout>
<Layout.Sider
className={css`
height: 100%;
left: 0;
top: 0;
background: rgba(0, 0, 0, 0);
z-index: 100;
.ant-layout-sider-children {
top: 46px;
position: fixed;
width: 200px;
height: calc(100vh - 46px);
}
`}
theme={'light'}
>
<Menu
selectedKeys={[currentSetting?.pluginName]}
style={{ height: 'calc(100vh - 46px)', overflowY: 'auto', overflowX: 'hidden' }}
onClick={({ key }) => {
const plugin = settings.find((item) => item.name === key);
if (plugin.children?.length) {
return navigate(getFirstDeepChildPath(plugin.children));
} else {
return navigate(plugin.path);
}
}}
items={sidebarMenus}
/>
</Layout.Sider>
<Layout.Content>
{currentSetting && (
<PageHeader
className={styles.pageHeader}
style={{
paddingBottom: currentPlugin.children?.length > 0 ? 0 : theme.paddingSM,
}}
ghost={false}
title={currentPlugin.title}
footer={
currentPlugin.children?.length > 0 && (
<Menu
style={{ marginLeft: -theme.margin }}
onClick={({ key }) => {
navigate(app.pluginSettingsManager.getRoutePath(key));
}}
selectedKeys={[currentSetting?.name]}
mode="horizontal"
items={getMenuItems(currentPlugin.children)}
></Menu>
)
}
/>
)}
<div className={styles.pageContent}>
{currentSetting ? (
<Outlet />
) : (
<Result status="404" title="404" subTitle="Sorry, the page you visited does not exist." />
)}
</div>
</Layout.Content>
</Layout>
</div>
);
};