feat: improve action schema component
This commit is contained in:
parent
0c83c16391
commit
43393b4d44
@ -3,11 +3,11 @@ import { ISchema, useForm } from '@formily/react';
|
|||||||
import { uid } from '@formily/shared';
|
import { uid } from '@formily/shared';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { PluginManager } from '../plugin-manager';
|
import { PluginManager } from '../plugin-manager';
|
||||||
import { SchemaComponent, useActionVisible, VisibleContext } from '../schema-component';
|
import { ActionContext, SchemaComponent, useActionContext } from '../schema-component';
|
||||||
import { RoleTable } from './RolePermissionManager';
|
import { RoleTable } from './RolePermissionManager';
|
||||||
|
|
||||||
const useCloseAction = () => {
|
const useCloseAction = () => {
|
||||||
const { setVisible } = useActionVisible();
|
const { setVisible } = useActionContext();
|
||||||
const form = useForm();
|
const form = useForm();
|
||||||
return {
|
return {
|
||||||
async run() {
|
async run() {
|
||||||
@ -39,7 +39,7 @@ const schema: ISchema = {
|
|||||||
export const ACLShortcut = () => {
|
export const ACLShortcut = () => {
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
return (
|
return (
|
||||||
<VisibleContext.Provider value={[visible, setVisible]}>
|
<ActionContext.Provider value={{ visible, setVisible }}>
|
||||||
<PluginManager.Toolbar.Item
|
<PluginManager.Toolbar.Item
|
||||||
icon={<LockOutlined />}
|
icon={<LockOutlined />}
|
||||||
title={'角色和权限'}
|
title={'角色和权限'}
|
||||||
@ -48,6 +48,6 @@ export const ACLShortcut = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<SchemaComponent components={{ RoleTable }} scope={{ useCloseAction }} schema={schema} />
|
<SchemaComponent components={{ RoleTable }} scope={{ useCloseAction }} schema={schema} />
|
||||||
</VisibleContext.Provider>
|
</ActionContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -3,11 +3,11 @@ import { ISchema, useForm } from '@formily/react';
|
|||||||
import { uid } from '@formily/shared';
|
import { uid } from '@formily/shared';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { PluginManager } from '../plugin-manager';
|
import { PluginManager } from '../plugin-manager';
|
||||||
import { SchemaComponent, useActionVisible, VisibleContext } from '../schema-component';
|
import { ActionContext, SchemaComponent, useActionContext } from '../schema-component';
|
||||||
import { ConfigurationTable } from './Configuration';
|
import { ConfigurationTable } from './Configuration';
|
||||||
|
|
||||||
const useCloseAction = () => {
|
const useCloseAction = () => {
|
||||||
const { setVisible } = useActionVisible();
|
const { setVisible } = useActionContext();
|
||||||
const form = useForm();
|
const form = useForm();
|
||||||
return {
|
return {
|
||||||
async run() {
|
async run() {
|
||||||
@ -38,7 +38,7 @@ const schema: ISchema = {
|
|||||||
export const CollectionManagerShortcut = () => {
|
export const CollectionManagerShortcut = () => {
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
return (
|
return (
|
||||||
<VisibleContext.Provider value={[visible, setVisible]}>
|
<ActionContext.Provider value={{ visible, setVisible }}>
|
||||||
<PluginManager.Toolbar.Item
|
<PluginManager.Toolbar.Item
|
||||||
icon={<DatabaseOutlined />}
|
icon={<DatabaseOutlined />}
|
||||||
title={'数据表配置'}
|
title={'数据表配置'}
|
||||||
@ -47,6 +47,6 @@ export const CollectionManagerShortcut = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<SchemaComponent scope={{ useCloseAction }} schema={schema} components={{ ConfigurationTable }} />
|
<SchemaComponent scope={{ useCloseAction }} schema={schema} components={{ ConfigurationTable }} />
|
||||||
</VisibleContext.Provider>
|
</ActionContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import React, { useState } from 'react';
|
|
||||||
import { VerifiedOutlined } from '@ant-design/icons';
|
import { VerifiedOutlined } from '@ant-design/icons';
|
||||||
import { ISchema, useForm } from '@formily/react';
|
import { ISchema, useForm } from '@formily/react';
|
||||||
import { PluginManager, SchemaComponent, useActionVisible, VisibleContext } from '@nocobase/client';
|
import { ActionContext, PluginManager, SchemaComponent, useActionContext } from '@nocobase/client';
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
const useCloseAction = () => {
|
const useCloseAction = () => {
|
||||||
const { setVisible } = useActionVisible();
|
const { setVisible } = useActionContext();
|
||||||
const form = useForm();
|
const form = useForm();
|
||||||
return {
|
return {
|
||||||
async run() {
|
async run() {
|
||||||
@ -51,7 +51,7 @@ export const Plugin2 = () => null;
|
|||||||
Plugin2.ToolbarItem = () => {
|
Plugin2.ToolbarItem = () => {
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
return (
|
return (
|
||||||
<VisibleContext.Provider value={[visible, setVisible]}>
|
<ActionContext.Provider value={{ visible, setVisible }}>
|
||||||
<PluginManager.Toolbar.Item
|
<PluginManager.Toolbar.Item
|
||||||
icon={<VerifiedOutlined />}
|
icon={<VerifiedOutlined />}
|
||||||
title={'Plugin2'}
|
title={'Plugin2'}
|
||||||
@ -60,6 +60,6 @@ Plugin2.ToolbarItem = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<SchemaComponent scope={{ useCloseAction }} schema={schema} />
|
<SchemaComponent scope={{ useCloseAction }} schema={schema} />
|
||||||
</VisibleContext.Provider>
|
</ActionContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import React, { useState } from 'react';
|
|
||||||
import { VerifiedOutlined } from '@ant-design/icons';
|
import { VerifiedOutlined } from '@ant-design/icons';
|
||||||
import { ISchema, useForm } from '@formily/react';
|
import { ISchema, useForm } from '@formily/react';
|
||||||
import { PluginManager, SchemaComponent, useActionVisible, VisibleContext } from '@nocobase/client';
|
import { ActionContext, PluginManager, SchemaComponent, useActionContext } from '@nocobase/client';
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
const useCloseAction = () => {
|
const useCloseAction = () => {
|
||||||
const { setVisible } = useActionVisible();
|
const { setVisible } = useActionContext();
|
||||||
const form = useForm();
|
const form = useForm();
|
||||||
return {
|
return {
|
||||||
async run() {
|
async run() {
|
||||||
@ -51,7 +51,7 @@ export const Plugin4 = () => null;
|
|||||||
Plugin4.ToolbarItem = () => {
|
Plugin4.ToolbarItem = () => {
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
return (
|
return (
|
||||||
<VisibleContext.Provider value={[visible, setVisible]}>
|
<ActionContext.Provider value={{ visible, setVisible }}>
|
||||||
<PluginManager.Toolbar.Item
|
<PluginManager.Toolbar.Item
|
||||||
icon={<VerifiedOutlined />}
|
icon={<VerifiedOutlined />}
|
||||||
title={'Plugin4'}
|
title={'Plugin4'}
|
||||||
@ -60,6 +60,6 @@ Plugin4.ToolbarItem = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<SchemaComponent scope={{ useCloseAction }} schema={schema} />
|
<SchemaComponent scope={{ useCloseAction }} schema={schema} />
|
||||||
</VisibleContext.Provider>
|
</ActionContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -44,7 +44,7 @@ Plugin1.ToolbarItem = () => {
|
|||||||
Plugin2.ToolbarItem = () => {
|
Plugin2.ToolbarItem = () => {
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
return (
|
return (
|
||||||
<VisibleContext.Provider value={[visible, setVisible]}>
|
<ActionContext.Provider value={{ visible, setVisible }}>
|
||||||
<PluginManager.Toolbar.Item
|
<PluginManager.Toolbar.Item
|
||||||
icon={<VerifiedOutlined />}
|
icon={<VerifiedOutlined />}
|
||||||
title={'Plugin2'}
|
title={'Plugin2'}
|
||||||
@ -53,7 +53,7 @@ Plugin2.ToolbarItem = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<SchemaComponent scope={{ useCloseAction }} schema={schema} />
|
<SchemaComponent scope={{ useCloseAction }} schema={schema} />
|
||||||
</VisibleContext.Provider>
|
</ActionContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
import { observer, RecursionField, useField, useFieldSchema } from '@formily/react';
|
||||||
|
import React from 'react';
|
||||||
|
import { useActionContext } from '.';
|
||||||
|
import { ActionDrawer } from './Action.Drawer';
|
||||||
|
import { ActionModal } from './Action.Modal';
|
||||||
|
import { ActionPage } from './Action.Page';
|
||||||
|
import { ComposedActionDrawer } from './types';
|
||||||
|
|
||||||
|
export const ActionContainer: ComposedActionDrawer = observer((props: any) => {
|
||||||
|
const { openMode } = useActionContext();
|
||||||
|
if (openMode === 'drawer') {
|
||||||
|
return <ActionDrawer footerNodeName={'Action.Container.Footer'} {...props} />;
|
||||||
|
}
|
||||||
|
if (openMode === 'modal') {
|
||||||
|
return <ActionModal footerNodeName={'Action.Container.Footer'} {...props} />;
|
||||||
|
}
|
||||||
|
return <ActionPage footerNodeName={'Action.Container.Footer'} {...props} />;
|
||||||
|
});
|
||||||
|
|
||||||
|
ActionContainer.Footer = observer(() => {
|
||||||
|
const field = useField();
|
||||||
|
const schema = useFieldSchema();
|
||||||
|
return <RecursionField basePath={field.address} schema={schema} onlyRenderProperties />;
|
||||||
|
});
|
||||||
|
|
||||||
|
export default ActionContainer;
|
@ -1,17 +1,18 @@
|
|||||||
import { css } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
import { observer, RecursionField, useField, useFieldSchema } from '@formily/react';
|
import { observer, RecursionField, useField, useFieldSchema } from '@formily/react';
|
||||||
import { Drawer } from 'antd';
|
import { Drawer } from 'antd';
|
||||||
import React, { useContext } from 'react';
|
import React from 'react';
|
||||||
import { createPortal } from 'react-dom';
|
import { createPortal } from 'react-dom';
|
||||||
import { VisibleContext } from './context';
|
import { useActionContext } from './hooks';
|
||||||
import { ComposedActionDrawer } from './types';
|
import { ComposedActionDrawer } from './types';
|
||||||
|
|
||||||
export const ActionDrawer: ComposedActionDrawer = observer((props) => {
|
export const ActionDrawer: ComposedActionDrawer = observer((props) => {
|
||||||
const [visible, setVisible] = useContext(VisibleContext);
|
const { footerNodeName = 'Action.Drawer.Footer', ...others } = props;
|
||||||
|
const { visible, setVisible } = useActionContext();
|
||||||
const schema = useFieldSchema();
|
const schema = useFieldSchema();
|
||||||
const field = useField();
|
const field = useField();
|
||||||
const footerSchema = schema.reduceProperties((buf, s) => {
|
const footerSchema = schema.reduceProperties((buf, s) => {
|
||||||
if (s['x-component'] === 'Action.Drawer.Footer') {
|
if (s['x-component'] === footerNodeName) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
return buf;
|
return buf;
|
||||||
@ -22,7 +23,7 @@ export const ActionDrawer: ComposedActionDrawer = observer((props) => {
|
|||||||
<Drawer
|
<Drawer
|
||||||
width={'50%'}
|
width={'50%'}
|
||||||
title={schema.title}
|
title={schema.title}
|
||||||
{...props}
|
{...others}
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
visible={visible}
|
visible={visible}
|
||||||
onClose={() => setVisible(false)}
|
onClose={() => setVisible(false)}
|
||||||
@ -43,7 +44,7 @@ export const ActionDrawer: ComposedActionDrawer = observer((props) => {
|
|||||||
schema={schema}
|
schema={schema}
|
||||||
onlyRenderProperties
|
onlyRenderProperties
|
||||||
filterProperties={(s) => {
|
filterProperties={(s) => {
|
||||||
return s['x-component'] === 'Action.Drawer.Footer';
|
return s['x-component'] === footerNodeName;
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -55,7 +56,7 @@ export const ActionDrawer: ComposedActionDrawer = observer((props) => {
|
|||||||
schema={schema}
|
schema={schema}
|
||||||
onlyRenderProperties
|
onlyRenderProperties
|
||||||
filterProperties={(s) => {
|
filterProperties={(s) => {
|
||||||
return s['x-component'] !== 'Action.Drawer.Footer';
|
return s['x-component'] !== footerNodeName;
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Drawer>,
|
</Drawer>,
|
||||||
|
@ -0,0 +1,75 @@
|
|||||||
|
import { css } from '@emotion/css';
|
||||||
|
import { observer, RecursionField, useField, useFieldSchema } from '@formily/react';
|
||||||
|
import { Modal } from 'antd';
|
||||||
|
import React from 'react';
|
||||||
|
import { createPortal } from 'react-dom';
|
||||||
|
import { useActionContext } from '.';
|
||||||
|
import { ComposedActionDrawer } from './types';
|
||||||
|
|
||||||
|
export const ActionModal: ComposedActionDrawer = observer((props) => {
|
||||||
|
const { footerNodeName = 'Action.Modal.Footer', ...others } = props;
|
||||||
|
const { visible, setVisible } = useActionContext();
|
||||||
|
const schema = useFieldSchema();
|
||||||
|
const field = useField();
|
||||||
|
const footerSchema = schema.reduceProperties((buf, s) => {
|
||||||
|
if (s['x-component'] === footerNodeName) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{createPortal(
|
||||||
|
<Modal
|
||||||
|
// width={'50%'}
|
||||||
|
title={schema.title}
|
||||||
|
{...others}
|
||||||
|
destroyOnClose
|
||||||
|
visible={visible}
|
||||||
|
onCancel={() => setVisible(false)}
|
||||||
|
footer={
|
||||||
|
footerSchema && (
|
||||||
|
<div
|
||||||
|
className={css`
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
width: 100%;
|
||||||
|
.ant-btn {
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
<RecursionField
|
||||||
|
basePath={field.address}
|
||||||
|
schema={schema}
|
||||||
|
onlyRenderProperties
|
||||||
|
filterProperties={(s) => {
|
||||||
|
return s['x-component'] === footerNodeName;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<RecursionField
|
||||||
|
basePath={field.address}
|
||||||
|
schema={schema}
|
||||||
|
onlyRenderProperties
|
||||||
|
filterProperties={(s) => {
|
||||||
|
return s['x-component'] !== footerNodeName;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Modal>,
|
||||||
|
document.body,
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
ActionModal.Footer = observer(() => {
|
||||||
|
const field = useField();
|
||||||
|
const schema = useFieldSchema();
|
||||||
|
return <RecursionField basePath={field.address} schema={schema} onlyRenderProperties />;
|
||||||
|
});
|
||||||
|
|
||||||
|
export default ActionModal;
|
@ -0,0 +1,74 @@
|
|||||||
|
import { css } from '@emotion/css';
|
||||||
|
import { observer, RecursionField, SchemaExpressionScopeContext, useField, useFieldSchema } from '@formily/react';
|
||||||
|
import React, { useContext } from 'react';
|
||||||
|
import { createPortal } from 'react-dom';
|
||||||
|
import { useActionContext } from '.';
|
||||||
|
import { ComposedActionDrawer } from './types';
|
||||||
|
|
||||||
|
const useScope = (key: string) => {
|
||||||
|
const scope = useContext(SchemaExpressionScopeContext);
|
||||||
|
return scope[key];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ActionPage: ComposedActionDrawer = observer((props: any) => {
|
||||||
|
const { footerNodeName = 'Action.Page.Footer', ...others } = props;
|
||||||
|
const { containerRefKey, visible, setVisible } = useActionContext();
|
||||||
|
const containerRef = useScope(containerRefKey);
|
||||||
|
const schema = useFieldSchema();
|
||||||
|
const field = useField();
|
||||||
|
const footerSchema = schema.reduceProperties((buf, s) => {
|
||||||
|
if (s['x-component'] === footerNodeName) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{containerRef?.current &&
|
||||||
|
visible &&
|
||||||
|
createPortal(
|
||||||
|
<div>
|
||||||
|
<RecursionField
|
||||||
|
basePath={field.address}
|
||||||
|
schema={schema}
|
||||||
|
onlyRenderProperties
|
||||||
|
filterProperties={(s) => {
|
||||||
|
return s['x-component'] !== footerNodeName;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{footerSchema && (
|
||||||
|
<div
|
||||||
|
className={css`
|
||||||
|
display: flex;
|
||||||
|
/* justify-content: flex-end; */
|
||||||
|
/* flex-direction: row-reverse; */
|
||||||
|
width: 100%;
|
||||||
|
.ant-btn {
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
<RecursionField
|
||||||
|
basePath={field.address}
|
||||||
|
schema={schema}
|
||||||
|
onlyRenderProperties
|
||||||
|
filterProperties={(s) => {
|
||||||
|
return s['x-component'] === footerNodeName;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>,
|
||||||
|
containerRef?.current,
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
ActionPage.Footer = observer(() => {
|
||||||
|
const field = useField();
|
||||||
|
const schema = useFieldSchema();
|
||||||
|
return <RecursionField basePath={field.address} schema={schema} onlyRenderProperties />;
|
||||||
|
});
|
||||||
|
|
||||||
|
export default ActionPage;
|
@ -1,19 +1,22 @@
|
|||||||
import { observer, RecursionField, useField, useFieldSchema } from '@formily/react';
|
import { observer, RecursionField, useField, useFieldSchema } from '@formily/react';
|
||||||
import { Button } from 'antd';
|
import { Button } from 'antd';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
|
import ActionContainer from './Action.Container';
|
||||||
import { ActionDrawer } from './Action.Drawer';
|
import { ActionDrawer } from './Action.Drawer';
|
||||||
import { VisibleContext } from './context';
|
import { ActionModal } from './Action.Modal';
|
||||||
|
import { ActionPage } from './Action.Page';
|
||||||
|
import { ActionContext } from './context';
|
||||||
import { useA } from './hooks';
|
import { useA } from './hooks';
|
||||||
import { ComposedAction } from './types';
|
import { ComposedAction } from './types';
|
||||||
|
|
||||||
export const Action: ComposedAction = observer((props) => {
|
export const Action: ComposedAction = observer((props: any) => {
|
||||||
const { useAction = useA, onClick, ...others } = props;
|
const { openMode, containerRefKey, useAction = useA, onClick, ...others } = props;
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
const schema = useFieldSchema();
|
const schema = useFieldSchema();
|
||||||
const field = useField();
|
const field = useField();
|
||||||
const { run } = useAction();
|
const { run } = useAction();
|
||||||
return (
|
return (
|
||||||
<VisibleContext.Provider value={[visible, setVisible]}>
|
<ActionContext.Provider value={{ visible, setVisible, openMode, containerRefKey }}>
|
||||||
<Button
|
<Button
|
||||||
{...others}
|
{...others}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
@ -25,10 +28,13 @@ export const Action: ComposedAction = observer((props) => {
|
|||||||
{field.title}
|
{field.title}
|
||||||
</Button>
|
</Button>
|
||||||
<RecursionField basePath={field.address} schema={schema} onlyRenderProperties />
|
<RecursionField basePath={field.address} schema={schema} onlyRenderProperties />
|
||||||
</VisibleContext.Provider>
|
</ActionContext.Provider>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
Action.Drawer = ActionDrawer;
|
Action.Drawer = ActionDrawer;
|
||||||
|
Action.Modal = ActionModal;
|
||||||
|
Action.Container = ActionContainer;
|
||||||
|
Action.Page = ActionPage;
|
||||||
|
|
||||||
export default Action;
|
export default Action;
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
import { createContext } from 'react';
|
import { createContext } from 'react';
|
||||||
|
|
||||||
export const VisibleContext = createContext<[boolean, any]>([false, () => {}]);
|
export const ActionContext = createContext<ActionContextProps>({});
|
||||||
|
|
||||||
|
export interface ActionContextProps {
|
||||||
|
visible?: boolean;
|
||||||
|
setVisible?: (v: boolean) => void;
|
||||||
|
openMode?: 'drawer' | 'modal' | 'page';
|
||||||
|
containerRefKey?: string;
|
||||||
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import React from 'react';
|
|
||||||
import { observer, ISchema, useForm } from '@formily/react';
|
|
||||||
import { SchemaComponent, SchemaComponentProvider, Form, Action, useActionVisible } from '@nocobase/client';
|
|
||||||
import { FormItem, Input } from '@formily/antd';
|
import { FormItem, Input } from '@formily/antd';
|
||||||
|
import { ISchema, observer, useForm } from '@formily/react';
|
||||||
|
import { Action, Form, SchemaComponent, SchemaComponentProvider, useActionContext } from '@nocobase/client';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
const useCloseAction = () => {
|
const useCloseAction = () => {
|
||||||
const { setVisible } = useActionVisible();
|
const { setVisible } = useActionContext();
|
||||||
const form = useForm();
|
const form = useForm();
|
||||||
return {
|
return {
|
||||||
async run() {
|
async run() {
|
||||||
|
@ -1,18 +1,17 @@
|
|||||||
import React, { useState } from 'react';
|
import { FormItem, Input } from '@formily/antd';
|
||||||
import { observer, ISchema, useForm } from '@formily/react';
|
import { ISchema, observer, useForm } from '@formily/react';
|
||||||
import {
|
import {
|
||||||
|
Action,
|
||||||
|
ActionContext,
|
||||||
|
Form,
|
||||||
SchemaComponent,
|
SchemaComponent,
|
||||||
SchemaComponentProvider,
|
SchemaComponentProvider,
|
||||||
Form,
|
useActionContext
|
||||||
Action,
|
|
||||||
useActionVisible,
|
|
||||||
VisibleContext,
|
|
||||||
} from '@nocobase/client';
|
} from '@nocobase/client';
|
||||||
import { FormItem, Input } from '@formily/antd';
|
import React, { useState } from 'react';
|
||||||
import { Button } from 'antd';
|
|
||||||
|
|
||||||
const useCloseAction = () => {
|
const useCloseAction = () => {
|
||||||
const { setVisible } = useActionVisible();
|
const { setVisible } = useActionContext();
|
||||||
const form = useForm();
|
const form = useForm();
|
||||||
return {
|
return {
|
||||||
async run() {
|
async run() {
|
||||||
@ -58,10 +57,10 @@ export default observer(() => {
|
|||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
return (
|
return (
|
||||||
<SchemaComponentProvider components={{ Form, Action, Input, FormItem }}>
|
<SchemaComponentProvider components={{ Form, Action, Input, FormItem }}>
|
||||||
<VisibleContext.Provider value={[visible, setVisible]}>
|
<ActionContext.Provider value={{ visible, setVisible }}>
|
||||||
<a onClick={() => setVisible(true)}>Open</a>
|
<a onClick={() => setVisible(true)}>Open</a>
|
||||||
<SchemaComponent scope={{ useCloseAction }} schema={schema} />
|
<SchemaComponent scope={{ useCloseAction }} schema={schema} />
|
||||||
</VisibleContext.Provider>
|
</ActionContext.Provider>
|
||||||
</SchemaComponentProvider>
|
</SchemaComponentProvider>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
107
packages/client/src/schema-component/antd/action/demos/demo3.tsx
Normal file
107
packages/client/src/schema-component/antd/action/demos/demo3.tsx
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
import { FormItem, Input } from '@formily/antd';
|
||||||
|
import { Field } from '@formily/core';
|
||||||
|
import { ISchema, observer, useField, useForm } from '@formily/react';
|
||||||
|
import { Action, Form, SchemaComponent, SchemaComponentProvider, useActionContext } from '@nocobase/client';
|
||||||
|
import { Select } from 'antd';
|
||||||
|
import React, { useRef } from 'react';
|
||||||
|
|
||||||
|
const useCloseAction = () => {
|
||||||
|
const { setVisible } = useActionContext();
|
||||||
|
const form = useForm();
|
||||||
|
return {
|
||||||
|
async run() {
|
||||||
|
setVisible(false);
|
||||||
|
form.submit((values) => {
|
||||||
|
console.log(values);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const Editable = observer((props) => {
|
||||||
|
const field = useField<Field>();
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div style={{ marginBottom: 24 }}>
|
||||||
|
打开方式:
|
||||||
|
<Select
|
||||||
|
value={field.componentProps.openMode}
|
||||||
|
style={{ width: 100 }}
|
||||||
|
onChange={(value) => {
|
||||||
|
field.componentProps.openMode = value;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Select.Option value={'drawer'}>Drawer</Select.Option>
|
||||||
|
<Select.Option value={'modal'}>Modal</Select.Option>
|
||||||
|
<Select.Option value={'page'}>Page</Select.Option>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
{props.children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const schema: ISchema = {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
action1: {
|
||||||
|
'x-decorator': 'Editable',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-component-props': {
|
||||||
|
type: 'primary',
|
||||||
|
openMode: 'modal',
|
||||||
|
containerRefKey: 'containerRef',
|
||||||
|
},
|
||||||
|
type: 'void',
|
||||||
|
title: 'Open',
|
||||||
|
properties: {
|
||||||
|
drawer1: {
|
||||||
|
'x-component': 'Action.Container',
|
||||||
|
'x-component-props': {},
|
||||||
|
type: 'void',
|
||||||
|
title: 'Modal Title',
|
||||||
|
properties: {
|
||||||
|
hello1: {
|
||||||
|
title: 'T1',
|
||||||
|
'x-content': 'Hello',
|
||||||
|
},
|
||||||
|
footer1: {
|
||||||
|
'x-component': 'Action.Container.Footer',
|
||||||
|
type: 'void',
|
||||||
|
properties: {
|
||||||
|
close1: {
|
||||||
|
title: 'Close',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-component-props': {
|
||||||
|
useAction: '{{ useCloseAction }}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
submit: {
|
||||||
|
title: 'Submit',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-component-props': {
|
||||||
|
type: 'primary',
|
||||||
|
useAction: '{{ useCloseAction }}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default observer(() => {
|
||||||
|
const containerRef = useRef();
|
||||||
|
return (
|
||||||
|
<SchemaComponentProvider
|
||||||
|
scope={{ containerRef, useCloseAction }}
|
||||||
|
components={{ Editable, Form, Action, Input, FormItem }}
|
||||||
|
>
|
||||||
|
<SchemaComponent schema={schema} />
|
||||||
|
<div ref={containerRef}></div>
|
||||||
|
</SchemaComponentProvider>
|
||||||
|
);
|
||||||
|
});
|
@ -1,6 +1,6 @@
|
|||||||
import { useForm } from '@formily/react';
|
import { useForm } from '@formily/react';
|
||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
import { VisibleContext } from './context';
|
import { ActionContext } from './context';
|
||||||
|
|
||||||
export const useA = () => {
|
export const useA = () => {
|
||||||
return {
|
return {
|
||||||
@ -8,13 +8,21 @@ export const useA = () => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useActionVisible = () => {
|
export const useActionContext = () => {
|
||||||
const [visible, setVisible] = useContext(VisibleContext);
|
const ctx = useContext(ActionContext);
|
||||||
return { visible, setVisible };
|
|
||||||
|
return {
|
||||||
|
...ctx,
|
||||||
|
setVisible(visible: boolean) {
|
||||||
|
if (ctx.openMode !== 'page') {
|
||||||
|
ctx.setVisible(visible);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useCloseAction = () => {
|
export const useCloseAction = () => {
|
||||||
const [, setVisible] = useContext(VisibleContext);
|
const { setVisible } = useContext(ActionContext);
|
||||||
const form = useForm();
|
const form = useForm();
|
||||||
return {
|
return {
|
||||||
async run() {
|
async run() {
|
||||||
|
@ -10,22 +10,15 @@ group:
|
|||||||
|
|
||||||
## Nodes
|
## Nodes
|
||||||
|
|
||||||
已确定的节点:
|
|
||||||
|
|
||||||
- Action
|
- Action
|
||||||
- Action.URL
|
|
||||||
- Action.Link
|
|
||||||
- Action.Drawer
|
- Action.Drawer
|
||||||
- Action.Drawer.Footer
|
- Action.Drawer.Footer
|
||||||
- Action.Modal
|
- Action.Modal
|
||||||
- Action.Modal.Footer
|
- Action.Modal.Footer
|
||||||
- Action.Popover
|
- Action.Drawer
|
||||||
|
- Action.Drawer.Footer
|
||||||
不确定的节点:
|
- Action.Container
|
||||||
|
- Action.Container.Footer
|
||||||
- Action.Group
|
|
||||||
- Action.Dropdown
|
|
||||||
- Action.Window
|
|
||||||
- ActionBar
|
- ActionBar
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
@ -34,8 +27,12 @@ group:
|
|||||||
|
|
||||||
<code src="./demos/demo1.tsx"/>
|
<code src="./demos/demo1.tsx"/>
|
||||||
|
|
||||||
### VisibleContext + Action.Drawer
|
### ActionContext + Action.Drawer
|
||||||
|
|
||||||
只配置 Action.Drawer,而不需要 Action,通过 VisibleContext 自定义按钮。
|
只配置 Action.Drawer,而不需要 Action,结合 ActionContext 自定义按钮。
|
||||||
|
|
||||||
<code src="./demos/demo2.tsx"/>
|
<code src="./demos/demo2.tsx"/>
|
||||||
|
|
||||||
|
### 不同的打开方式
|
||||||
|
|
||||||
|
<code src="./demos/demo3.tsx"/>
|
||||||
|
@ -11,6 +11,6 @@ export type ComposedAction = React.FC<ActionProps> & {
|
|||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ComposedActionDrawer = React.FC<DrawerProps> & {
|
export type ComposedActionDrawer = React.FC<DrawerProps & { footerNodeName?: string }> & {
|
||||||
Footer?: React.FC;
|
Footer?: React.FC;
|
||||||
};
|
};
|
||||||
|
@ -15,7 +15,7 @@ import { toArr } from '@formily/shared';
|
|||||||
import { Button, Drawer, Select, Space, Tag } from 'antd';
|
import { Button, Drawer, Select, Space, Tag } from 'antd';
|
||||||
import React, { createContext, useContext, useMemo, useState } from 'react';
|
import React, { createContext, useContext, useMemo, useState } from 'react';
|
||||||
import { useAttach } from '../../hooks/useAttach';
|
import { useAttach } from '../../hooks/useAttach';
|
||||||
import { VisibleContext } from '../action';
|
import { ActionContext } from '../action';
|
||||||
|
|
||||||
const InputRecordPicker: React.FC = (props) => {
|
const InputRecordPicker: React.FC = (props) => {
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
@ -130,13 +130,11 @@ RecordPicker.SelectedItem = () => {
|
|||||||
const fieldSchema = useFieldSchema();
|
const fieldSchema = useFieldSchema();
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
return (
|
return (
|
||||||
<>
|
<ActionContext.Provider value={{ visible, setVisible }}>
|
||||||
<VisibleContext.Provider value={[visible, setVisible]}>
|
<Tag style={{ cursor: 'pointer' }} onClick={() => setVisible(true)}>
|
||||||
<Tag style={{ cursor: 'pointer' }} onClick={() => setVisible(true)}>
|
{ctx.record?.name}
|
||||||
{ctx.record?.name}
|
</Tag>
|
||||||
</Tag>
|
<RecursionField onlyRenderProperties schema={fieldSchema}></RecursionField>
|
||||||
<RecursionField onlyRenderProperties schema={fieldSchema}></RecursionField>
|
</ActionContext.Provider>
|
||||||
</VisibleContext.Provider>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -4,10 +4,10 @@ import { uid } from '@formily/shared';
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { useSystemSettings } from '.';
|
import { useSystemSettings } from '.';
|
||||||
import { PluginManager, useRequest } from '..';
|
import { PluginManager, useRequest } from '..';
|
||||||
import { SchemaComponent, useActionVisible, VisibleContext } from '../schema-component';
|
import { ActionContext, SchemaComponent, useActionContext } from '../schema-component';
|
||||||
|
|
||||||
const useCloseAction = () => {
|
const useCloseAction = () => {
|
||||||
const { setVisible } = useActionVisible();
|
const { setVisible } = useActionContext();
|
||||||
// const form = useForm();
|
// const form = useForm();
|
||||||
return {
|
return {
|
||||||
async run() {
|
async run() {
|
||||||
@ -24,7 +24,7 @@ const useSystemSettingsValues = (props, options) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const useSaveSystemSettingsValues = () => {
|
const useSaveSystemSettingsValues = () => {
|
||||||
const { setVisible } = useActionVisible();
|
const { setVisible } = useActionContext();
|
||||||
const form = useForm();
|
const form = useForm();
|
||||||
const { mutate } = useSystemSettings();
|
const { mutate } = useSystemSettings();
|
||||||
return {
|
return {
|
||||||
@ -112,7 +112,7 @@ const schema: ISchema = {
|
|||||||
export const SystemSettingsShortcut = () => {
|
export const SystemSettingsShortcut = () => {
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
return (
|
return (
|
||||||
<VisibleContext.Provider value={[visible, setVisible]}>
|
<ActionContext.Provider value={{ visible, setVisible }}>
|
||||||
<PluginManager.Toolbar.Item
|
<PluginManager.Toolbar.Item
|
||||||
eventKey={'ACLAction'}
|
eventKey={'ACLAction'}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@ -125,6 +125,6 @@ export const SystemSettingsShortcut = () => {
|
|||||||
scope={{ useSaveSystemSettingsValues, useSystemSettingsValues, useCloseAction }}
|
scope={{ useSaveSystemSettingsValues, useSystemSettingsValues, useCloseAction }}
|
||||||
schema={schema}
|
schema={schema}
|
||||||
/>
|
/>
|
||||||
</VisibleContext.Provider>
|
</ActionContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -2,10 +2,10 @@ import { ISchema, useForm } from '@formily/react';
|
|||||||
import { uid } from '@formily/shared';
|
import { uid } from '@formily/shared';
|
||||||
import { Menu } from 'antd';
|
import { Menu } from 'antd';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { SchemaComponent, useActionVisible, useRequest, VisibleContext } from '../';
|
import { ActionContext, SchemaComponent, useActionContext, useRequest } from '../';
|
||||||
|
|
||||||
const useCloseAction = () => {
|
const useCloseAction = () => {
|
||||||
const { setVisible } = useActionVisible();
|
const { setVisible } = useActionContext();
|
||||||
const form = useForm();
|
const form = useForm();
|
||||||
return {
|
return {
|
||||||
async run() {
|
async run() {
|
||||||
@ -30,7 +30,7 @@ const useCurrentUserValues = (props, options) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const useSaveCurrentUserValues = () => {
|
const useSaveCurrentUserValues = () => {
|
||||||
const { setVisible } = useActionVisible();
|
const { setVisible } = useActionContext();
|
||||||
const form = useForm();
|
const form = useForm();
|
||||||
return {
|
return {
|
||||||
async run() {
|
async run() {
|
||||||
@ -90,7 +90,7 @@ const schema: ISchema = {
|
|||||||
export const ProfileAction = () => {
|
export const ProfileAction = () => {
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
return (
|
return (
|
||||||
<VisibleContext.Provider value={[visible, setVisible]}>
|
<ActionContext.Provider value={{ visible, setVisible }}>
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
eventKey={'ProfileAction'}
|
eventKey={'ProfileAction'}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@ -100,6 +100,6 @@ export const ProfileAction = () => {
|
|||||||
个人资料
|
个人资料
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
<SchemaComponent scope={{ useCurrentUserValues, useCloseAction, useSaveCurrentUserValues }} schema={schema} />
|
<SchemaComponent scope={{ useCurrentUserValues, useCloseAction, useSaveCurrentUserValues }} schema={schema} />
|
||||||
</VisibleContext.Provider>
|
</ActionContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user