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 { Menu, Space } from 'antd';
|
||||
import React, { createContext, useContext } from 'react';
|
||||
import { Menu, Space, Tooltip } from 'antd';
|
||||
import { SettingOutlined, MoreOutlined, DesktopOutlined } from '@ant-design/icons';
|
||||
import { CurrentUser, DesignableSwitch, CollectionManagerAction, ACLAction, SystemSettings } from '../';
|
||||
import { get } from 'lodash';
|
||||
import { PluginManagerProvider } from '.';
|
||||
import { PluginManagerContext, PluginManagerProvider } from '.';
|
||||
|
||||
export const PluginManager = () => null;
|
||||
// TODO
|
||||
export const PluginManager: any = () => null;
|
||||
|
||||
PluginManager.Provider = PluginManagerProvider;
|
||||
|
||||
const ToolbarItemContext = createContext(null);
|
||||
|
||||
PluginManager.Toolbar = (props: any) => {
|
||||
const components = { CurrentUser, DesignableSwitch, CollectionManagerAction, ACLAction, SystemSettings };
|
||||
const items = [
|
||||
{
|
||||
action: 'DesignableSwitch',
|
||||
pin: true,
|
||||
},
|
||||
{
|
||||
action: 'CollectionManagerAction',
|
||||
pin: true,
|
||||
},
|
||||
{
|
||||
action: 'ACLAction',
|
||||
pin: true,
|
||||
},
|
||||
{
|
||||
action: 'SystemSettings.Action',
|
||||
},
|
||||
];
|
||||
const CurrentUserDropdown = get(components, 'CurrentUser.Dropdown');
|
||||
const { components } = useContext(PluginManagerContext);
|
||||
const { items = [] } = props;
|
||||
return (
|
||||
<Menu selectable={false} mode={'horizontal'} theme={'dark'}>
|
||||
{items
|
||||
.filter((item) => item.pin)
|
||||
.map((item) => {
|
||||
const Action = get(components, item.action);
|
||||
return Action && <Action />;
|
||||
})}
|
||||
<Menu.SubMenu key={'more'} title={<MoreOutlined />}>
|
||||
<div style={{ display: 'inline-block' }}>
|
||||
<Menu style={{ width: '100%' }} selectable={false} mode={'horizontal'} theme={'dark'}>
|
||||
{items
|
||||
.filter((item) => !item.pin)
|
||||
.filter((item) => item.pin)
|
||||
.map((item) => {
|
||||
const Action = get(components, item.action);
|
||||
return Action && <Action />;
|
||||
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>
|
||||
<CurrentUserDropdown />
|
||||
</Menu>
|
||||
<Menu.SubMenu key={'more'} title={<MoreOutlined />}>
|
||||
{items
|
||||
.filter((item) => !item.pin)
|
||||
.map((item) => {
|
||||
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
|
||||
|
||||
```tsx | pure
|
||||
<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>
|
||||
```
|
||||
## PluginManagerProvider
|
||||
|
||||
## 扩展
|
||||
## 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
|
||||
import React from 'react';
|
||||
import { Button, Menu } from 'antd';
|
||||
import { HighlightOutlined } from '@ant-design/icons';
|
||||
|
||||
export const DesignableSwitch = () => {
|
||||
const { designable, setDesignable } = useDesignable();
|
||||
Plugin1.ToolbarItem = () => {
|
||||
return (
|
||||
<Menu.Item key={'DesignableSwitch'} eventKey={'DesignableSwitch'}>
|
||||
<HighlightOutlined />
|
||||
</Menu.Item>
|
||||
<PluginManager.Toolbar.Item
|
||||
icon={<DatabaseOutlined />}
|
||||
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