feat(client): plugin manager toolbar
This commit is contained in:
parent
e7918b7887
commit
d1f9d3e25d
65
packages/client/src/acl/ACLAction.tsx
Normal file
65
packages/client/src/acl/ACLAction.tsx
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import { Menu } from 'antd';
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { LockOutlined } from '@ant-design/icons';
|
||||||
|
import { SchemaComponent, useActionVisible, VisibleContext } from '../schema-component';
|
||||||
|
import { ISchema, useForm } from '@formily/react';
|
||||||
|
|
||||||
|
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 ACLAction = () => {
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
|
return (
|
||||||
|
<VisibleContext.Provider value={[visible, setVisible]}>
|
||||||
|
<Menu.Item
|
||||||
|
eventKey={'ACLAction'}
|
||||||
|
onClick={() => {
|
||||||
|
setVisible(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<LockOutlined />
|
||||||
|
</Menu.Item>
|
||||||
|
<SchemaComponent scope={{ useCloseAction }} schema={schema} />
|
||||||
|
</VisibleContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
@ -1,2 +1,3 @@
|
|||||||
export * from './ACLProvider';
|
export * from './ACLProvider';
|
||||||
export * from './RolePermissionManager';
|
export * from './RolePermissionManager';
|
||||||
|
export * from './ACLAction';
|
||||||
|
@ -12,6 +12,7 @@ import {
|
|||||||
AntdConfigProvider,
|
AntdConfigProvider,
|
||||||
SchemaComponentProvider,
|
SchemaComponentProvider,
|
||||||
Menu,
|
Menu,
|
||||||
|
Action,
|
||||||
} from '@nocobase/client';
|
} from '@nocobase/client';
|
||||||
import { I18nextProvider } from 'react-i18next';
|
import { I18nextProvider } from 'react-i18next';
|
||||||
import { Spin } from 'antd';
|
import { Spin } from 'antd';
|
||||||
@ -23,7 +24,7 @@ const providers = [
|
|||||||
[APIClientProvider, { apiClient }],
|
[APIClientProvider, { apiClient }],
|
||||||
[I18nextProvider, { i18n }],
|
[I18nextProvider, { i18n }],
|
||||||
[AntdConfigProvider, { remoteLocale: true }],
|
[AntdConfigProvider, { remoteLocale: true }],
|
||||||
[SchemaComponentProvider, { components: { Menu } }],
|
[SchemaComponentProvider, { components: { Menu, Action } }],
|
||||||
[RouteSwitchProvider, { components: { AuthLayout, AdminLayout } }],
|
[RouteSwitchProvider, { components: { AuthLayout, AdminLayout } }],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -0,0 +1,65 @@
|
|||||||
|
import { Menu } from 'antd';
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { DatabaseOutlined } from '@ant-design/icons';
|
||||||
|
import { SchemaComponent, useActionVisible, VisibleContext } from '../schema-component';
|
||||||
|
import { ISchema, useForm } from '@formily/react';
|
||||||
|
|
||||||
|
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 CollectionManagerAction = () => {
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
|
return (
|
||||||
|
<VisibleContext.Provider value={[visible, setVisible]}>
|
||||||
|
<Menu.Item
|
||||||
|
eventKey={'CollectionManagerAction'}
|
||||||
|
onClick={() => {
|
||||||
|
setVisible(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DatabaseOutlined />
|
||||||
|
</Menu.Item>
|
||||||
|
<SchemaComponent scope={{ useCloseAction }} schema={schema} />
|
||||||
|
</VisibleContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
@ -5,3 +5,4 @@ export * from './context';
|
|||||||
export * from './hooks';
|
export * from './hooks';
|
||||||
export * from './types';
|
export * from './types';
|
||||||
export * from './CollectionField';
|
export * from './CollectionField';
|
||||||
|
export * from './CollectionManagerAction';
|
||||||
|
65
packages/client/src/current-user/ProfileAction.tsx
Normal file
65
packages/client/src/current-user/ProfileAction.tsx
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import { Menu } from 'antd';
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { DatabaseOutlined } from '@ant-design/icons';
|
||||||
|
import { SchemaComponent, useActionVisible, VisibleContext } from '../schema-component';
|
||||||
|
import { ISchema, useForm } from '@formily/react';
|
||||||
|
|
||||||
|
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 ProfileAction = () => {
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
|
return (
|
||||||
|
<VisibleContext.Provider value={[visible, setVisible]}>
|
||||||
|
<Menu.Item
|
||||||
|
eventKey={'ProfileAction'}
|
||||||
|
onClick={() => {
|
||||||
|
setVisible(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
个人资料
|
||||||
|
</Menu.Item>
|
||||||
|
<SchemaComponent scope={{ useCloseAction }} schema={schema} />
|
||||||
|
</VisibleContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
@ -1,3 +1,19 @@
|
|||||||
export function CurrentUser() {
|
import { Menu } from 'antd';
|
||||||
|
import React from 'react';
|
||||||
}
|
import { MoreOutlined, DesktopOutlined } from '@ant-design/icons';
|
||||||
|
import { ProfileAction } from './ProfileAction';
|
||||||
|
|
||||||
|
export const CurrentUser = () => null;
|
||||||
|
|
||||||
|
CurrentUser.Dropdown = () => {
|
||||||
|
return (
|
||||||
|
// @ts-ignore
|
||||||
|
<Menu.SubMenu eventKey={'CurrentUser.Dropdown'} title={'超级管理员'}>
|
||||||
|
<ProfileAction />
|
||||||
|
<Menu.Item>切换角色</Menu.Item>
|
||||||
|
<Menu.Item>语言设置</Menu.Item>
|
||||||
|
<Menu.Divider />
|
||||||
|
<Menu.Item>注销</Menu.Item>
|
||||||
|
</Menu.SubMenu>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
@ -14,3 +14,4 @@ export * from './system-settings';
|
|||||||
export * from './application';
|
export * from './application';
|
||||||
export * from './record-provider';
|
export * from './record-provider';
|
||||||
export * from './async-data-provider';
|
export * from './async-data-provider';
|
||||||
|
export * from './plugin-manager';
|
||||||
|
53
packages/client/src/plugin-manager/PluginManager.tsx
Normal file
53
packages/client/src/plugin-manager/PluginManager.tsx
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import React, { createContext } from 'react';
|
||||||
|
import { Menu, Space } from 'antd';
|
||||||
|
import { SettingOutlined, MoreOutlined, DesktopOutlined } from '@ant-design/icons';
|
||||||
|
import { CurrentUser, DesignableSwitch, CollectionManagerAction, ACLAction, SystemSettings } from '../';
|
||||||
|
import { get } from 'lodash';
|
||||||
|
import { PluginManagerProvider } from '.';
|
||||||
|
|
||||||
|
export const PluginManager = () => null;
|
||||||
|
|
||||||
|
PluginManager.Provider = PluginManagerProvider;
|
||||||
|
|
||||||
|
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');
|
||||||
|
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 />}>
|
||||||
|
{items
|
||||||
|
.filter((item) => !item.pin)
|
||||||
|
.map((item) => {
|
||||||
|
const Action = get(components, item.action);
|
||||||
|
return Action && <Action />;
|
||||||
|
})}
|
||||||
|
<Menu.Divider></Menu.Divider>
|
||||||
|
<Menu.Item icon={<SettingOutlined />}>管理插件</Menu.Item>
|
||||||
|
</Menu.SubMenu>
|
||||||
|
<CurrentUserDropdown />
|
||||||
|
</Menu>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,7 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { PluginManagerContext } from './context';
|
||||||
|
|
||||||
|
export const PluginManagerProvider: React.FC<any> = (props) => {
|
||||||
|
const { components, children } = props;
|
||||||
|
return <PluginManagerContext.Provider value={{ components }}>{children}</PluginManagerContext.Provider>;
|
||||||
|
};
|
3
packages/client/src/plugin-manager/context.ts
Normal file
3
packages/client/src/plugin-manager/context.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { createContext } from 'react';
|
||||||
|
|
||||||
|
export const PluginManagerContext = createContext<any>({});
|
55
packages/client/src/plugin-manager/index.md
Normal file
55
packages/client/src/plugin-manager/index.md
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
---
|
||||||
|
nav:
|
||||||
|
path: /client
|
||||||
|
group:
|
||||||
|
path: /client
|
||||||
|
---
|
||||||
|
|
||||||
|
# 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>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 扩展
|
||||||
|
|
||||||
|
如何扩展插件的 `PluginManager.Toolbar.Item`
|
||||||
|
|
||||||
|
```tsx | pure
|
||||||
|
import React from 'react';
|
||||||
|
import { Button, Menu } from 'antd';
|
||||||
|
import { HighlightOutlined } from '@ant-design/icons';
|
||||||
|
|
||||||
|
export const DesignableSwitch = () => {
|
||||||
|
const { designable, setDesignable } = useDesignable();
|
||||||
|
return (
|
||||||
|
<Menu.Item key={'DesignableSwitch'} eventKey={'DesignableSwitch'}>
|
||||||
|
<HighlightOutlined />
|
||||||
|
</Menu.Item>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
```
|
3
packages/client/src/plugin-manager/index.ts
Normal file
3
packages/client/src/plugin-manager/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export * from './context';
|
||||||
|
export * from './PluginManager';
|
||||||
|
export * from './PluginManagerProvider';
|
@ -14,12 +14,12 @@ group:
|
|||||||
- Layout.Header
|
- Layout.Header
|
||||||
- SiteTitle
|
- SiteTitle
|
||||||
- Menu(SchemaComponent)
|
- Menu(SchemaComponent)
|
||||||
- PluginActionBar
|
- PluginManager.Toolbar
|
||||||
- Designable.Action(引用)
|
- DesignableAction
|
||||||
- CollectionManager.Action(引用)
|
- CollectionManager.Action
|
||||||
- ACL.Action(引用)
|
- ACL.Action
|
||||||
- SystemSettings.Action(引用)
|
- SystemSettings.Action
|
||||||
- CurrentUser.Dropdown(引用)
|
- CurrentUser.Dropdown
|
||||||
- Layout.Sider
|
- Layout.Sider
|
||||||
- SideMenu(随 Menu 联动的)
|
- SideMenu(随 Menu 联动的)
|
||||||
- Layout.Content
|
- Layout.Content
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import React, { useRef, useState } from 'react';
|
import React, { useRef, useState } from 'react';
|
||||||
import { Layout, Spin } from 'antd';
|
import { Layout } from 'antd';
|
||||||
import { useRoute } from '../..';
|
import { useRoute } from '../../hooks';
|
||||||
import { findMenuItem, RemoteSchemaComponent } from '../../../schema-component';
|
import { useHistory, useRouteMatch } from 'react-router-dom';
|
||||||
import { Redirect, useHistory, useRouteMatch } from 'react-router-dom';
|
import { findMenuItem, RemoteSchemaComponent, PluginManager } from '../../../';
|
||||||
|
|
||||||
export function AdminLayout(props: any) {
|
export function AdminLayout(props: any) {
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
@ -19,28 +19,33 @@ export function AdminLayout(props: any) {
|
|||||||
const [hidden, setHidden] = useState(false);
|
const [hidden, setHidden] = useState(false);
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
<Layout.Header>
|
<Layout.Header style={{ position: 'relative' }}>
|
||||||
<RemoteSchemaComponent
|
<div>
|
||||||
hidden={hidden}
|
<RemoteSchemaComponent
|
||||||
uid={route.uiSchemaUid}
|
hidden={hidden}
|
||||||
scope={{ onSelect, sideMenuRef, defaultSelectedUid }}
|
uid={route.uiSchemaUid}
|
||||||
schemaTransform={(data) => {
|
scope={{ onSelect, sideMenuRef, defaultSelectedUid }}
|
||||||
data['x-component-props']['defaultSelectedUid'] = defaultSelectedUid;
|
schemaTransform={(data) => {
|
||||||
return data;
|
data['x-component-props']['defaultSelectedUid'] = defaultSelectedUid;
|
||||||
}}
|
return data;
|
||||||
onSuccess={(data) => {
|
}}
|
||||||
if (defaultSelectedUid) {
|
onSuccess={(data) => {
|
||||||
return;
|
if (defaultSelectedUid) {
|
||||||
}
|
return;
|
||||||
setHidden(true);
|
}
|
||||||
setTimeout(() => setHidden(false), 11);
|
setHidden(true);
|
||||||
const s = findMenuItem(data?.data);
|
setTimeout(() => setHidden(false), 11);
|
||||||
if (s) {
|
const s = findMenuItem(data?.data);
|
||||||
setSchema(s);
|
if (s) {
|
||||||
history.push(`/admin/${s['x-uid']}`);
|
setSchema(s);
|
||||||
}
|
history.push(`/admin/${s['x-uid']}`);
|
||||||
}}
|
}
|
||||||
/>
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div style={{ position: 'absolute', top: 0, right: 0 }}>
|
||||||
|
<PluginManager.Toolbar />
|
||||||
|
</div>
|
||||||
</Layout.Header>
|
</Layout.Header>
|
||||||
<Layout>
|
<Layout>
|
||||||
<Layout.Sider style={{ display: 'none' }} theme={'light'} ref={sideMenuRef}></Layout.Sider>
|
<Layout.Sider style={{ display: 'none' }} theme={'light'} ref={sideMenuRef}></Layout.Sider>
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { observer, ISchema, useForm } from '@formily/react';
|
||||||
|
import {
|
||||||
|
SchemaComponent,
|
||||||
|
SchemaComponentProvider,
|
||||||
|
Form,
|
||||||
|
Action,
|
||||||
|
useActionVisible,
|
||||||
|
VisibleContext,
|
||||||
|
} from '@nocobase/client';
|
||||||
|
import { FormItem, Input } from '@formily/antd';
|
||||||
|
import { Button } from 'antd';
|
||||||
|
|
||||||
|
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 default observer(() => {
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
|
return (
|
||||||
|
<SchemaComponentProvider components={{ Form, Action, Input, FormItem }}>
|
||||||
|
<VisibleContext.Provider value={[visible, setVisible]}>
|
||||||
|
<a onClick={() => setVisible(true)}>Open</a>
|
||||||
|
<SchemaComponent scope={{ useCloseAction }} schema={schema} />
|
||||||
|
</VisibleContext.Provider>
|
||||||
|
</SchemaComponentProvider>
|
||||||
|
);
|
||||||
|
});
|
@ -30,4 +30,12 @@ group:
|
|||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
|
### Action + Action.Drawer
|
||||||
|
|
||||||
<code src="./demos/demo1.tsx"/>
|
<code src="./demos/demo1.tsx"/>
|
||||||
|
|
||||||
|
### VisibleContext + Action.Drawer
|
||||||
|
|
||||||
|
只配置 Action.Drawer,而不需要 Action,通过 VisibleContext 自定义按钮。
|
||||||
|
|
||||||
|
<code src="./demos/demo2.tsx"/>
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Button, Menu } from 'antd';
|
||||||
|
import { HighlightOutlined } from '@ant-design/icons';
|
||||||
|
import cls from 'classnames';
|
||||||
|
import { useDesignable } from '..';
|
||||||
|
|
||||||
|
export const DesignableSwitch = () => {
|
||||||
|
const { designable, setDesignable } = useDesignable();
|
||||||
|
return (
|
||||||
|
<Menu.Item key={'DesignableSwitch'} eventKey={'DesignableSwitch'}>
|
||||||
|
<HighlightOutlined />
|
||||||
|
</Menu.Item>
|
||||||
|
);
|
||||||
|
};
|
@ -3,3 +3,4 @@ export * from './SchemaComponent';
|
|||||||
export * from './SchemaComponentProvider';
|
export * from './SchemaComponentProvider';
|
||||||
export * from './SchemaOptionsExpressionScopeProvider';
|
export * from './SchemaOptionsExpressionScopeProvider';
|
||||||
export * from './RemoteSchemaComponent';
|
export * from './RemoteSchemaComponent';
|
||||||
|
export * from './DesignableSwitch';
|
||||||
|
@ -216,7 +216,7 @@ export class Designable {
|
|||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
export function useDesignable() {
|
export function useDesignable() {
|
||||||
const { designable, refresh, reset } = useContext(SchemaComponentContext);
|
const { designable, setDesignable, refresh, reset } = useContext(SchemaComponentContext);
|
||||||
const DesignableBar = () => {
|
const DesignableBar = () => {
|
||||||
return <></>;
|
return <></>;
|
||||||
};
|
};
|
||||||
@ -229,6 +229,7 @@ export function useDesignable() {
|
|||||||
designable,
|
designable,
|
||||||
reset,
|
reset,
|
||||||
refresh,
|
refresh,
|
||||||
|
setDesignable,
|
||||||
DesignableBar,
|
DesignableBar,
|
||||||
on: dn.on.bind(dn),
|
on: dn.on.bind(dn),
|
||||||
// TODO
|
// TODO
|
||||||
|
65
packages/client/src/system-settings/SystemSettingsAction.tsx
Normal file
65
packages/client/src/system-settings/SystemSettingsAction.tsx
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import { Menu } from 'antd';
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { LockOutlined } from '@ant-design/icons';
|
||||||
|
import { SchemaComponent, useActionVisible, VisibleContext } from '../schema-component';
|
||||||
|
import { ISchema, useForm } from '@formily/react';
|
||||||
|
|
||||||
|
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 SystemSettingsAction = () => {
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
|
return (
|
||||||
|
<VisibleContext.Provider value={[visible, setVisible]}>
|
||||||
|
<Menu.Item
|
||||||
|
eventKey={'ACLAction'}
|
||||||
|
onClick={() => {
|
||||||
|
setVisible(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<LockOutlined /> 系统设置
|
||||||
|
</Menu.Item>
|
||||||
|
<SchemaComponent scope={{ useCloseAction }} schema={schema} />
|
||||||
|
</VisibleContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
@ -1,3 +1,5 @@
|
|||||||
export function SystemSettings() {
|
import { SystemSettingsAction } from './SystemSettingsAction';
|
||||||
|
|
||||||
}
|
export const SystemSettings = () => null;
|
||||||
|
|
||||||
|
SystemSettings.Action = SystemSettingsAction;
|
||||||
|
Loading…
Reference in New Issue
Block a user