From 39e80fad61784de73380de4690dcd05a77b035c5 Mon Sep 17 00:00:00 2001 From: chenos Date: Mon, 7 Feb 2022 23:30:24 +0800 Subject: [PATCH] feat(client): add x-initializer parameter to schema --- .../antd/action/ActionBar.tsx | 32 ++++++ .../schema-component/antd/action/index.tsx | 2 + .../antd/array-table/ArrayTable.tsx | 11 ++- .../antd/array-table/demos/demo1.tsx | 5 +- .../client/src/schema-component/antd/index.ts | 1 + .../src/schema-component/hooks/index.ts | 1 + .../schema-component/hooks/useComponent.ts | 14 +++ .../schema-component/hooks/useDesignable.tsx | 15 ++- .../schema-initializer/SchemaInitializer.tsx | 11 +-- .../src/schema-initializer/demos/demo2.tsx | 97 ++++++------------- .../src/schema-initializer/demos/demo4.tsx | 70 +++++++++++-- 11 files changed, 163 insertions(+), 96 deletions(-) create mode 100644 packages/client/src/schema-component/antd/action/ActionBar.tsx create mode 100644 packages/client/src/schema-component/hooks/useComponent.ts diff --git a/packages/client/src/schema-component/antd/action/ActionBar.tsx b/packages/client/src/schema-component/antd/action/ActionBar.tsx new file mode 100644 index 000000000..41e540263 --- /dev/null +++ b/packages/client/src/schema-component/antd/action/ActionBar.tsx @@ -0,0 +1,32 @@ +import { RecursionField, useFieldSchema } from '@formily/react'; +import { Space } from 'antd'; +import React from 'react'; +import { useComponent } from '../../hooks'; + +export const ActionBar = () => { + const fieldSchema = useFieldSchema(); + const Initializer = useComponent(fieldSchema['x-initializer']); + return ( +
+
+ + {fieldSchema.mapProperties((schema, key) => { + if (schema['x-align'] !== 'left') { + return null; + } + return ; + })} + + + {fieldSchema.mapProperties((schema, key) => { + if (schema['x-align'] === 'left') { + return null; + } + return ; + })} + +
+ {Initializer && } +
+ ); +}; diff --git a/packages/client/src/schema-component/antd/action/index.tsx b/packages/client/src/schema-component/antd/action/index.tsx index 685a31103..7ac34ea01 100644 --- a/packages/client/src/schema-component/antd/action/index.tsx +++ b/packages/client/src/schema-component/antd/action/index.tsx @@ -1,3 +1,5 @@ export * from './Action'; +export * from './ActionBar'; export * from './context'; export * from './hooks'; + 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 77f9aabc1..4d1653940 100644 --- a/packages/client/src/schema-component/antd/array-table/ArrayTable.tsx +++ b/packages/client/src/schema-component/antd/array-table/ArrayTable.tsx @@ -2,7 +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'; +import { useComponent } from '../../hooks'; const isColumnComponent = (schema: Schema) => { return schema['x-component']?.endsWith('.Column') > -1; @@ -11,6 +11,7 @@ const isColumnComponent = (schema: Schema) => { const useTableColumns = () => { const field = useField(); const schema = useFieldSchema(); + const Initializer = useComponent(schema['x-initializer']); const columns = schema .reduceProperties((buf, s) => { if (isColumnComponent(s)) { @@ -28,13 +29,13 @@ const useTableColumns = () => { } as TableColumnProps; }); console.log(columns); - if (!schema['x-column-initializer']) { + if (!Initializer) { return columns; } return columns.concat({ - title: , - dataIndex: 'TableColumnInitializeButton', - key: 'TableColumnInitializeButton', + title: , + dataIndex: 'TableColumnInitializer', + key: 'TableColumnInitializer', }); }; 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 0b91265ae..5eec566fb 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, ArrayTableColumnInitializer, Input, SchemaComponent, SchemaComponentProvider } from '@nocobase/client'; +import { ArrayTable, Input, SchemaComponent, SchemaComponentProvider } from '@nocobase/client'; import React from 'react'; const schema: ISchema = { @@ -19,7 +19,6 @@ const schema: ISchema = { ], 'x-decorator': 'FormItem', 'x-component': 'ArrayTable', - 'x-column-initializer': 'ArrayTableColumnInitializer', 'x-component-props': { rowKey: 'id', }, @@ -61,7 +60,7 @@ const schema: ISchema = { export default () => { return ( - + ); diff --git a/packages/client/src/schema-component/antd/index.ts b/packages/client/src/schema-component/antd/index.ts index e25c66b15..708006e87 100644 --- a/packages/client/src/schema-component/antd/index.ts +++ b/packages/client/src/schema-component/antd/index.ts @@ -29,3 +29,4 @@ export * from './time-picker'; export * from './tree-select'; export * from './upload'; export * from './void-table'; + diff --git a/packages/client/src/schema-component/hooks/index.ts b/packages/client/src/schema-component/hooks/index.ts index 44019bb65..faa42e391 100644 --- a/packages/client/src/schema-component/hooks/index.ts +++ b/packages/client/src/schema-component/hooks/index.ts @@ -1,5 +1,6 @@ export * from './useAttach'; export * from './useCompile'; +export * from './useComponent'; export * from './useDesignable'; export * from './useFieldProps'; export * from './useSchemaComponentContext'; diff --git a/packages/client/src/schema-component/hooks/useComponent.ts b/packages/client/src/schema-component/hooks/useComponent.ts new file mode 100644 index 000000000..85070d503 --- /dev/null +++ b/packages/client/src/schema-component/hooks/useComponent.ts @@ -0,0 +1,14 @@ +import { SchemaOptionsContext } from '@formily/react'; +import { get } from 'lodash'; +import { useContext } from 'react'; + +export const useComponent = (component: any) => { + if (!component) { + return null; + } + if (typeof component !== 'string') { + return component; + } + const { components } = useContext(SchemaOptionsContext); + return get(components, component); +}; diff --git a/packages/client/src/schema-component/hooks/useDesignable.tsx b/packages/client/src/schema-component/hooks/useDesignable.tsx index 28025d56e..76756e890 100644 --- a/packages/client/src/schema-component/hooks/useDesignable.tsx +++ b/packages/client/src/schema-component/hooks/useDesignable.tsx @@ -1,5 +1,6 @@ -import { ISchema, Schema, useField, useFieldSchema } from '@formily/react'; +import { ISchema, Schema, SchemaOptionsContext, useField, useFieldSchema } from '@formily/react'; import { uid } from '@formily/shared'; +import get from 'lodash/get'; import set from 'lodash/set'; import React, { useContext } from 'react'; import { SchemaComponentContext } from '../context'; @@ -250,7 +251,7 @@ export class Designable { const { wrap = defaultWrap, removeEmptyParents } = options; if (Schema.isSchemaInstance(schema)) { schema.parent.removeProperty(schema.name); - console.log('insertAfterEnd', removeEmptyParents) + console.log('insertAfterEnd', removeEmptyParents); if (removeEmptyParents) { this.removeIfChildrenEmpty(schema.parent); } @@ -281,6 +282,7 @@ export class Designable { // TODO export function useDesignable() { const { designable, setDesignable, refresh, reset } = useContext(SchemaComponentContext); + const { components } = useContext(SchemaOptionsContext); const DesignableBar = () => { return <>; }; @@ -295,6 +297,15 @@ export function useDesignable() { refresh, setDesignable, DesignableBar, + findComponent(component: any) { + if (!component) { + return null; + } + if (typeof component !== 'string') { + return component; + } + return get(components, component); + }, on: dn.on.bind(dn), // TODO patch: (key: ISchema | string, value?: any) => { diff --git a/packages/client/src/schema-initializer/SchemaInitializer.tsx b/packages/client/src/schema-initializer/SchemaInitializer.tsx index 5b4693f3c..faf002f90 100644 --- a/packages/client/src/schema-initializer/SchemaInitializer.tsx +++ b/packages/client/src/schema-initializer/SchemaInitializer.tsx @@ -1,7 +1,6 @@ -import { observer, Schema, SchemaOptionsContext } from '@formily/react'; +import { observer, Schema } 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; @@ -12,8 +11,7 @@ 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 { insertAdjacent, findComponent } = useDesignable(); const menu = ( @@ -22,7 +20,7 @@ SchemaInitializer.Button = observer((props: any) => { return ; } if (item.component) { - const Component = typeof item.component === 'object' ? item.component : get(components, item.component); + const Component = findComponent(item.component); return ( Component && ( { if (!child.component) { return null; } - const Component = - typeof child.component === 'object' ? child.component : get(components, child.component); + const Component = findComponent(child.component); return ( Component && ( { - const field = useField(); - return ( -
- {field.title} -
- ); -}); - -const InitializerDemo = observer((props: any) => { +const InitializerButton = observer((props: any) => { return ( schema} - insertPosition={'beforeBegin'} + insertPosition={'beforeEnd'} + style={{ marginLeft: 8 }} items={[ { - title: 'Data blocks', + title: 'Enable actions', children: [ { - title: 'Table', - component: 'TableBlockInitializer', + title: 'Create', + key: 'create', + component: 'ActionInitializer', + schema: { + 'x-align': 'left', + }, }, { - title: 'Form', - component: 'FormBlockInitializer', + title: 'Update', + key: 'update', + component: 'ActionInitializer', }, ], }, @@ -39,81 +34,43 @@ const InitializerDemo = observer((props: any) => { ); }); -const TableBlockInitializer = (props) => { - const { insert } = props; +const ActionInitializer = (props) => { + const { title, schema, insert } = props; return ( } onClick={(info) => { - console.log({ info }); insert({ type: 'void', title: info.key, - 'x-component': 'Hello', - }); - }} - items={[ - { - type: 'itemGroup', - title: 'select a data source', - children: [ - { - key: 'users', - title: 'Users', - }, - { - key: 'posts', - title: 'Posts', - }, - ], - }, - ]} - > - Table - - ); -}; - -const FormBlockInitializer = (props) => { - const { insert } = props; - return ( - } - onClick={(info) => { - insert({ - type: 'void', - title: 'form', - 'x-component': 'Hello', + 'x-component': 'Action', + ...schema, }); }} > - Form + {title} ); }; export default function App() { return ( - + { + const fields = [ + { + key: 'field1', + title: 'Field1', + component: ColumnInitializer, + }, + { + key: 'field2', + title: 'Field2', + component: 'ColumnInitializer', + }, + ]; + return fields; +}; + +export const InitializerButton = observer((props: any) => { + return ( + schema} + insertPosition={'beforeEnd'} + items={[ + { + title: 'Display fields', + children: useTableColumnInitializerFields(), + }, + ]} + > + Configure columns + + ); +}); + +export const ColumnInitializer = (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} + + ); +}; + const schema = { type: 'object', properties: { @@ -18,7 +70,7 @@ const schema = { { id: 3, name: 'Name3' }, ], 'x-component': 'ArrayTable', - 'x-column-initializer': 'ArrayTableColumnInitializer', + 'x-initializer': 'InitializerButton', 'x-component-props': { rowKey: 'id', }, @@ -42,7 +94,7 @@ const schema = { export default function App() { return ( - + );