feat: add demo for plugin manager toolbar

This commit is contained in:
chenos 2022-01-19 22:21:20 +08:00
parent d1f9d3e25d
commit b49440da00
9 changed files with 320 additions and 78 deletions

View File

@ -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'}>
<div style={{ display: 'inline-block' }}>
<Menu style={{ width: '100%' }} selectable={false} mode={'horizontal'} theme={'dark'}>
{items
.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.SubMenu key={'more'} title={<MoreOutlined />}>
{items
.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>
</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>
);
};

View 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>
);
};

View File

@ -0,0 +1,5 @@
export * from './plugin1';
export * from './plugin2';
export * from './plugin3';
export * from './plugin4';
export * from './plugin5';

View 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');
}}
/>
);
};

View 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>
);
};

View 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');
}}
/>
);
};

View 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>
);
};

View 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');
}}
/>
);
};

View File

@ -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>
);
};
```