mirror of
https://github.com/nocobase/nocobase
synced 2024-11-15 12:40:50 +00:00
feat: add demo for plugin manager toolbar
This commit is contained in:
parent
d1f9d3e25d
commit
b49440da00
@ -1,53 +1,71 @@
|
|||||||
import React, { createContext } from 'react';
|
import React, { createContext, useContext } from 'react';
|
||||||
import { Menu, Space } from 'antd';
|
import { Menu, Space, Tooltip } from 'antd';
|
||||||
import { SettingOutlined, MoreOutlined, DesktopOutlined } from '@ant-design/icons';
|
import { SettingOutlined, MoreOutlined, DesktopOutlined } from '@ant-design/icons';
|
||||||
import { CurrentUser, DesignableSwitch, CollectionManagerAction, ACLAction, SystemSettings } from '../';
|
import { CurrentUser, DesignableSwitch, CollectionManagerAction, ACLAction, SystemSettings } from '../';
|
||||||
import { get } from 'lodash';
|
import { get } from 'lodash';
|
||||||
import { PluginManagerProvider } from '.';
|
import { PluginManagerContext, PluginManagerProvider } from '.';
|
||||||
|
|
||||||
export const PluginManager = () => null;
|
// TODO
|
||||||
|
export const PluginManager: any = () => null;
|
||||||
|
|
||||||
PluginManager.Provider = PluginManagerProvider;
|
PluginManager.Provider = PluginManagerProvider;
|
||||||
|
|
||||||
|
const ToolbarItemContext = createContext(null);
|
||||||
|
|
||||||
PluginManager.Toolbar = (props: any) => {
|
PluginManager.Toolbar = (props: any) => {
|
||||||
const components = { CurrentUser, DesignableSwitch, CollectionManagerAction, ACLAction, SystemSettings };
|
const { components } = useContext(PluginManagerContext);
|
||||||
const items = [
|
const { items = [] } = props;
|
||||||
{
|
|
||||||
action: 'DesignableSwitch',
|
|
||||||
pin: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
action: 'CollectionManagerAction',
|
|
||||||
pin: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
action: 'ACLAction',
|
|
||||||
pin: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
action: 'SystemSettings.Action',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
const CurrentUserDropdown = get(components, 'CurrentUser.Dropdown');
|
|
||||||
return (
|
return (
|
||||||
<Menu selectable={false} mode={'horizontal'} theme={'dark'}>
|
<div style={{ display: 'inline-block' }}>
|
||||||
{items
|
<Menu style={{ width: '100%' }} selectable={false} mode={'horizontal'} theme={'dark'}>
|
||||||
.filter((item) => item.pin)
|
|
||||||
.map((item) => {
|
|
||||||
const Action = get(components, item.action);
|
|
||||||
return Action && <Action />;
|
|
||||||
})}
|
|
||||||
<Menu.SubMenu key={'more'} title={<MoreOutlined />}>
|
|
||||||
{items
|
{items
|
||||||
.filter((item) => !item.pin)
|
.filter((item) => item.pin)
|
||||||
.map((item) => {
|
.map((item) => {
|
||||||
const Action = get(components, item.action);
|
const Action = get(components, item.component);
|
||||||
return Action && <Action />;
|
return (
|
||||||
|
Action && (
|
||||||
|
<ToolbarItemContext.Provider value={item}>
|
||||||
|
<Action />
|
||||||
|
</ToolbarItemContext.Provider>
|
||||||
|
)
|
||||||
|
);
|
||||||
})}
|
})}
|
||||||
<Menu.Divider></Menu.Divider>
|
<Menu.SubMenu key={'more'} title={<MoreOutlined />}>
|
||||||
<Menu.Item icon={<SettingOutlined />}>管理插件</Menu.Item>
|
{items
|
||||||
</Menu.SubMenu>
|
.filter((item) => !item.pin)
|
||||||
<CurrentUserDropdown />
|
.map((item) => {
|
||||||
</Menu>
|
const Action = get(components, item.component);
|
||||||
|
return (
|
||||||
|
Action && (
|
||||||
|
<ToolbarItemContext.Provider value={item}>
|
||||||
|
<Action />
|
||||||
|
</ToolbarItemContext.Provider>
|
||||||
|
)
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
<Menu.Divider></Menu.Divider>
|
||||||
|
<Menu.Item icon={<SettingOutlined />}>管理插件</Menu.Item>
|
||||||
|
</Menu.SubMenu>
|
||||||
|
</Menu>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
PluginManager.Toolbar.Item = (props) => {
|
||||||
|
const item = useContext(ToolbarItemContext);
|
||||||
|
const { icon, title, ...others } = props;
|
||||||
|
if (item.pin) {
|
||||||
|
return (
|
||||||
|
<Tooltip title={title}>
|
||||||
|
<Menu.Item {...others} eventKey={item.component}>
|
||||||
|
{icon}
|
||||||
|
</Menu.Item>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Menu.Item {...others} eventKey={item.component} icon={icon}>
|
||||||
|
{title}
|
||||||
|
</Menu.Item>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
34
packages/client/src/plugin-manager/demos/demo1.tsx
Normal file
34
packages/client/src/plugin-manager/demos/demo1.tsx
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Action, PluginManager, PluginManagerProvider, SchemaComponentProvider } from '@nocobase/client';
|
||||||
|
import * as plugins from './plugins';
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
return (
|
||||||
|
<SchemaComponentProvider components={{ Action }}>
|
||||||
|
<PluginManagerProvider components={plugins}>
|
||||||
|
<PluginManager.Toolbar
|
||||||
|
items={[
|
||||||
|
{
|
||||||
|
component: 'Plugin1.ToolbarItem',
|
||||||
|
pin: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Plugin2.ToolbarItem',
|
||||||
|
pin: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Plugin3.ToolbarItem',
|
||||||
|
pin: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Plugin4.ToolbarItem',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Plugin5.ToolbarItem',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</PluginManagerProvider>
|
||||||
|
</SchemaComponentProvider>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,5 @@
|
|||||||
|
export * from './plugin1';
|
||||||
|
export * from './plugin2';
|
||||||
|
export * from './plugin3';
|
||||||
|
export * from './plugin4';
|
||||||
|
export * from './plugin5';
|
17
packages/client/src/plugin-manager/demos/plugins/plugin1.tsx
Normal file
17
packages/client/src/plugin-manager/demos/plugins/plugin1.tsx
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { Menu } from 'antd';
|
||||||
|
import React from 'react';
|
||||||
|
import { SaveOutlined, KeyOutlined, DatabaseOutlined, VerifiedOutlined, NotificationOutlined } from '@ant-design/icons';
|
||||||
|
import { PluginManager } from '@nocobase/client';
|
||||||
|
|
||||||
|
export const Plugin1 = () => null;
|
||||||
|
Plugin1.ToolbarItem = () => {
|
||||||
|
return (
|
||||||
|
<PluginManager.Toolbar.Item
|
||||||
|
icon={<DatabaseOutlined />}
|
||||||
|
title={'Plugin1'}
|
||||||
|
onClick={() => {
|
||||||
|
alert('Plugin1');
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
65
packages/client/src/plugin-manager/demos/plugins/plugin2.tsx
Normal file
65
packages/client/src/plugin-manager/demos/plugins/plugin2.tsx
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { VerifiedOutlined } from '@ant-design/icons';
|
||||||
|
import { ISchema, useForm } from '@formily/react';
|
||||||
|
import { PluginManager, SchemaComponent, useActionVisible, VisibleContext } from '@nocobase/client';
|
||||||
|
|
||||||
|
const useCloseAction = () => {
|
||||||
|
const { setVisible } = useActionVisible();
|
||||||
|
const form = useForm();
|
||||||
|
return {
|
||||||
|
async run() {
|
||||||
|
setVisible(false);
|
||||||
|
form.submit((values) => {
|
||||||
|
console.log(values);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const schema: ISchema = {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
drawer1: {
|
||||||
|
'x-component': 'Action.Drawer',
|
||||||
|
type: 'void',
|
||||||
|
title: 'Drawer Title',
|
||||||
|
properties: {
|
||||||
|
hello1: {
|
||||||
|
'x-content': 'Hello',
|
||||||
|
title: 'T1',
|
||||||
|
},
|
||||||
|
footer1: {
|
||||||
|
'x-component': 'Action.Drawer.Footer',
|
||||||
|
type: 'void',
|
||||||
|
properties: {
|
||||||
|
close1: {
|
||||||
|
title: 'Close',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-component-props': {
|
||||||
|
useAction: '{{ useCloseAction }}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Plugin2 = () => null;
|
||||||
|
|
||||||
|
Plugin2.ToolbarItem = () => {
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
|
return (
|
||||||
|
<VisibleContext.Provider value={[visible, setVisible]}>
|
||||||
|
<PluginManager.Toolbar.Item
|
||||||
|
icon={<VerifiedOutlined />}
|
||||||
|
title={'Plugin2'}
|
||||||
|
onClick={() => {
|
||||||
|
setVisible(true);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<SchemaComponent scope={{ useCloseAction }} schema={schema} />
|
||||||
|
</VisibleContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
17
packages/client/src/plugin-manager/demos/plugins/plugin3.tsx
Normal file
17
packages/client/src/plugin-manager/demos/plugins/plugin3.tsx
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { Menu } from 'antd';
|
||||||
|
import React from 'react';
|
||||||
|
import { SaveOutlined, KeyOutlined, DatabaseOutlined, VerifiedOutlined, NotificationOutlined } from '@ant-design/icons';
|
||||||
|
import { PluginManager } from '@nocobase/client';
|
||||||
|
|
||||||
|
export const Plugin3 = () => null;
|
||||||
|
Plugin3.ToolbarItem = () => {
|
||||||
|
return (
|
||||||
|
<PluginManager.Toolbar.Item
|
||||||
|
icon={<DatabaseOutlined />}
|
||||||
|
title={'Plugin3'}
|
||||||
|
onClick={() => {
|
||||||
|
alert('Plugin3');
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
65
packages/client/src/plugin-manager/demos/plugins/plugin4.tsx
Normal file
65
packages/client/src/plugin-manager/demos/plugins/plugin4.tsx
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { VerifiedOutlined } from '@ant-design/icons';
|
||||||
|
import { ISchema, useForm } from '@formily/react';
|
||||||
|
import { PluginManager, SchemaComponent, useActionVisible, VisibleContext } from '@nocobase/client';
|
||||||
|
|
||||||
|
const useCloseAction = () => {
|
||||||
|
const { setVisible } = useActionVisible();
|
||||||
|
const form = useForm();
|
||||||
|
return {
|
||||||
|
async run() {
|
||||||
|
setVisible(false);
|
||||||
|
form.submit((values) => {
|
||||||
|
console.log(values);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const schema: ISchema = {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
drawer1: {
|
||||||
|
'x-component': 'Action.Drawer',
|
||||||
|
type: 'void',
|
||||||
|
title: 'Drawer Title',
|
||||||
|
properties: {
|
||||||
|
hello1: {
|
||||||
|
'x-content': 'Hello',
|
||||||
|
title: 'T1',
|
||||||
|
},
|
||||||
|
footer1: {
|
||||||
|
'x-component': 'Action.Drawer.Footer',
|
||||||
|
type: 'void',
|
||||||
|
properties: {
|
||||||
|
close1: {
|
||||||
|
title: 'Close',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-component-props': {
|
||||||
|
useAction: '{{ useCloseAction }}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Plugin4 = () => null;
|
||||||
|
|
||||||
|
Plugin4.ToolbarItem = () => {
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
|
return (
|
||||||
|
<VisibleContext.Provider value={[visible, setVisible]}>
|
||||||
|
<PluginManager.Toolbar.Item
|
||||||
|
icon={<VerifiedOutlined />}
|
||||||
|
title={'Plugin4'}
|
||||||
|
onClick={() => {
|
||||||
|
setVisible(true);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<SchemaComponent scope={{ useCloseAction }} schema={schema} />
|
||||||
|
</VisibleContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
17
packages/client/src/plugin-manager/demos/plugins/plugin5.tsx
Normal file
17
packages/client/src/plugin-manager/demos/plugins/plugin5.tsx
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { Menu } from 'antd';
|
||||||
|
import React from 'react';
|
||||||
|
import { SaveOutlined, KeyOutlined, DatabaseOutlined, VerifiedOutlined, NotificationOutlined } from '@ant-design/icons';
|
||||||
|
import { PluginManager } from '@nocobase/client';
|
||||||
|
|
||||||
|
export const Plugin5 = () => null;
|
||||||
|
Plugin5.ToolbarItem = () => {
|
||||||
|
return (
|
||||||
|
<PluginManager.Toolbar.Item
|
||||||
|
icon={<DatabaseOutlined />}
|
||||||
|
title={'Plugin5'}
|
||||||
|
onClick={() => {
|
||||||
|
alert('Plugin5');
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
@ -7,49 +7,53 @@ group:
|
|||||||
|
|
||||||
# PluginManager
|
# PluginManager
|
||||||
|
|
||||||
```tsx | pure
|
## PluginManagerProvider
|
||||||
<PluginManager.Provider components={{
|
|
||||||
CurrentUser,
|
|
||||||
DesignableSwitch,
|
|
||||||
CollectionManagerAction,
|
|
||||||
ACLAction,
|
|
||||||
SystemSettings,
|
|
||||||
}}>
|
|
||||||
<PluginManager.Toolbar items={[
|
|
||||||
{
|
|
||||||
action: 'DesignableSwitch',
|
|
||||||
pin: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
action: 'CollectionManagerAction',
|
|
||||||
pin: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
action: 'ACLAction',
|
|
||||||
pin: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
action: 'SystemSettings.Action',
|
|
||||||
},
|
|
||||||
]}/>
|
|
||||||
</PluginManager.Provider>
|
|
||||||
```
|
|
||||||
|
|
||||||
## 扩展
|
## PluginManager.Toolbar
|
||||||
|
|
||||||
如何扩展插件的 `PluginManager.Toolbar.Item`
|
插件管理器的工具栏,用于便捷的展示所有插件,不常用的可折叠显示。
|
||||||
|
|
||||||
|
<code src="./demos/demo1.tsx"/>
|
||||||
|
|
||||||
|
## PluginManager.Toolbar.Item
|
||||||
|
|
||||||
|
工具栏项,各个插件都可以配置自己的 `PluginManager.Toolbar.Item`
|
||||||
|
|
||||||
|
- `icon` pin 时,只显示 icon
|
||||||
|
- `title` pin 时,title 以 tooltip 的方式显示
|
||||||
|
|
||||||
|
最简单的示例
|
||||||
|
|
||||||
```tsx | pure
|
```tsx | pure
|
||||||
import React from 'react';
|
Plugin1.ToolbarItem = () => {
|
||||||
import { Button, Menu } from 'antd';
|
|
||||||
import { HighlightOutlined } from '@ant-design/icons';
|
|
||||||
|
|
||||||
export const DesignableSwitch = () => {
|
|
||||||
const { designable, setDesignable } = useDesignable();
|
|
||||||
return (
|
return (
|
||||||
<Menu.Item key={'DesignableSwitch'} eventKey={'DesignableSwitch'}>
|
<PluginManager.Toolbar.Item
|
||||||
<HighlightOutlined />
|
icon={<DatabaseOutlined />}
|
||||||
</Menu.Item>
|
title={'Plugin1'}
|
||||||
|
onClick={() => {
|
||||||
|
alert('Plugin1');
|
||||||
|
}}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
弹出抽屉
|
||||||
|
|
||||||
|
```tsx | pure
|
||||||
|
Plugin2.ToolbarItem = () => {
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
|
return (
|
||||||
|
<VisibleContext.Provider value={[visible, setVisible]}>
|
||||||
|
<PluginManager.Toolbar.Item
|
||||||
|
icon={<VerifiedOutlined />}
|
||||||
|
title={'Plugin2'}
|
||||||
|
onClick={() => {
|
||||||
|
setVisible(true);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<SchemaComponent scope={{ useCloseAction }} schema={schema} />
|
||||||
|
</VisibleContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
Loading…
Reference in New Issue
Block a user