diff --git a/packages/client/src/index.tsx b/packages/client/src/index.tsx index 69ab92cf9..8a9fa425a 100644 --- a/packages/client/src/index.tsx +++ b/packages/client/src/index.tsx @@ -15,6 +15,7 @@ export * from './plugin-manager'; export * from './record-provider'; export * from './route-switch'; export * from './schema-component'; +export * from './schema-initializer'; export * from './system-settings'; export * from './user'; diff --git a/packages/client/src/schema-component/antd/array-table/ArrayTable.tsx b/packages/client/src/schema-component/antd/array-table/ArrayTable.tsx index fe41c471e..77f9aabc1 100644 --- a/packages/client/src/schema-component/antd/array-table/ArrayTable.tsx +++ b/packages/client/src/schema-component/antd/array-table/ArrayTable.tsx @@ -2,6 +2,7 @@ import { ArrayField } from '@formily/core'; import { observer, RecursionField, Schema, useField, useFieldSchema } from '@formily/react'; import { Table, TableColumnProps } from 'antd'; import React from 'react'; +import { TableColumnInitializeButton } from './Initializer'; const isColumnComponent = (schema: Schema) => { return schema['x-component']?.endsWith('.Column') > -1; @@ -27,7 +28,14 @@ const useTableColumns = () => { } as TableColumnProps; }); console.log(columns); - return columns; + if (!schema['x-column-initializer']) { + return columns; + } + return columns.concat({ + title: , + dataIndex: 'TableColumnInitializeButton', + key: 'TableColumnInitializeButton', + }); }; type ArrayTableType = React.FC & { @@ -41,7 +49,7 @@ export const ArrayTable: ArrayTableType = observer((props) => { const { onChange, ...others } = props; return (
- +
); }); diff --git a/packages/client/src/schema-component/antd/array-table/Initializer.tsx b/packages/client/src/schema-component/antd/array-table/Initializer.tsx new file mode 100644 index 000000000..5fb47f3cd --- /dev/null +++ b/packages/client/src/schema-component/antd/array-table/Initializer.tsx @@ -0,0 +1,61 @@ +import { observer, useFieldSchema } from '@formily/react'; +import React from 'react'; +import { SchemaInitializer } from '../../../schema-initializer'; + +const useTableColumnInitializerFields = () => { + const fieldSchema = useFieldSchema(); + const fields = [ + { + key: 'field1', + title: 'Field1', + component: fieldSchema['x-column-initializer'], + }, + { + key: 'field2', + title: 'Field2', + component: fieldSchema['x-column-initializer'], + }, + ].filter((field) => field.component); + return fields; +}; + +export const TableColumnInitializeButton = observer((props: any) => { + return ( + schema} + insertPosition={'beforeEnd'} + items={[ + { + title: 'Display fields', + children: useTableColumnInitializerFields(), + }, + ]} + > + Configure columns + + ); +}); + +export const ArrayTableColumnInitializer = (props) => { + const { title, insert } = props; + return ( + { + insert({ + type: 'void', + title: 'Name', + 'x-component': 'ArrayTable.Column', + properties: { + name: { + type: 'string', + 'x-component': 'Input', + 'x-read-pretty': true, + }, + }, + }); + }} + > + {title} + + ); +}; diff --git a/packages/client/src/schema-component/antd/array-table/demos/demo1.tsx b/packages/client/src/schema-component/antd/array-table/demos/demo1.tsx index 5eec566fb..0b91265ae 100644 --- a/packages/client/src/schema-component/antd/array-table/demos/demo1.tsx +++ b/packages/client/src/schema-component/antd/array-table/demos/demo1.tsx @@ -3,7 +3,7 @@ */ import { FormItem } from '@formily/antd'; import { ISchema } from '@formily/react'; -import { ArrayTable, Input, SchemaComponent, SchemaComponentProvider } from '@nocobase/client'; +import { ArrayTable, ArrayTableColumnInitializer, Input, SchemaComponent, SchemaComponentProvider } from '@nocobase/client'; import React from 'react'; const schema: ISchema = { @@ -19,6 +19,7 @@ const schema: ISchema = { ], 'x-decorator': 'FormItem', 'x-component': 'ArrayTable', + 'x-column-initializer': 'ArrayTableColumnInitializer', 'x-component-props': { rowKey: 'id', }, @@ -60,7 +61,7 @@ const schema: ISchema = { export default () => { return ( - + ); diff --git a/packages/client/src/schema-component/antd/array-table/index.ts b/packages/client/src/schema-component/antd/array-table/index.ts index 18795279a..0a5379357 100644 --- a/packages/client/src/schema-component/antd/array-table/index.ts +++ b/packages/client/src/schema-component/antd/array-table/index.ts @@ -1 +1,3 @@ export * from './ArrayTable'; +export * from './Initializer'; + diff --git a/packages/client/src/schema-initializer/SchemaInitializer.tsx b/packages/client/src/schema-initializer/SchemaInitializer.tsx new file mode 100644 index 000000000..5b4693f3c --- /dev/null +++ b/packages/client/src/schema-initializer/SchemaInitializer.tsx @@ -0,0 +1,146 @@ +import { observer, Schema, SchemaOptionsContext } from '@formily/react'; +import { useDesignable } from '@nocobase/client'; +import { Button, Dropdown, Menu } from 'antd'; +import { get } from 'lodash'; +import React, { createContext, useContext, useState } from 'react'; + +const defaultWrap = (s: Schema) => s; + +export const SchemaInitializerItemContext = createContext(null); + +export const SchemaInitializer = () => null; + +SchemaInitializer.Button = observer((props: any) => { + const { wrap = defaultWrap, items = [], insertPosition, dropdown, ...others } = props; + const { insertAdjacent } = useDesignable(); + const { components } = useContext(SchemaOptionsContext); + + const menu = ( + + {items?.map((item, indexA) => { + if (item.type === 'divider') { + return ; + } + if (item.component) { + const Component = typeof item.component === 'object' ? item.component : get(components, item.component); + return ( + Component && ( + { + insertAdjacent(insertPosition, wrap(schema)); + }, + }} + > + { + insertAdjacent(insertPosition, wrap(schema)); + }} + /> + + ) + ); + } + return ( + item?.children?.length > 0 && ( + + {item?.children?.map((child, indexB) => { + if (!child.component) { + return null; + } + const Component = + typeof child.component === 'object' ? child.component : get(components, child.component); + return ( + Component && ( + { + insertAdjacent(insertPosition, wrap(schema)); + }, + }} + > + { + insertAdjacent(insertPosition, wrap(schema)); + }} + /> + + ) + ); + })} + + ) + ); + })} + + ); + const [visible, setVisible] = useState(false); + + return ( + { + setVisible(visible); + }} + {...dropdown} + overlay={menu} + > +