feat(client): add x-initializer parameter to schema
This commit is contained in:
parent
7cc821c06f
commit
39e80fad61
@ -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 (
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', width: '100%' }}>
|
||||
<Space>
|
||||
{fieldSchema.mapProperties((schema, key) => {
|
||||
if (schema['x-align'] !== 'left') {
|
||||
return null;
|
||||
}
|
||||
return <RecursionField key={key} name={key} schema={schema} />;
|
||||
})}
|
||||
</Space>
|
||||
<Space>
|
||||
{fieldSchema.mapProperties((schema, key) => {
|
||||
if (schema['x-align'] === 'left') {
|
||||
return null;
|
||||
}
|
||||
return <RecursionField key={key} name={key} schema={schema} />;
|
||||
})}
|
||||
</Space>
|
||||
</div>
|
||||
{Initializer && <Initializer />}
|
||||
</div>
|
||||
);
|
||||
};
|
@ -1,3 +1,5 @@
|
||||
export * from './Action';
|
||||
export * from './ActionBar';
|
||||
export * from './context';
|
||||
export * from './hooks';
|
||||
|
||||
|
@ -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<ArrayField>();
|
||||
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<any>;
|
||||
});
|
||||
console.log(columns);
|
||||
if (!schema['x-column-initializer']) {
|
||||
if (!Initializer) {
|
||||
return columns;
|
||||
}
|
||||
return columns.concat({
|
||||
title: <TableColumnInitializeButton />,
|
||||
dataIndex: 'TableColumnInitializeButton',
|
||||
key: 'TableColumnInitializeButton',
|
||||
title: <Initializer />,
|
||||
dataIndex: 'TableColumnInitializer',
|
||||
key: 'TableColumnInitializer',
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -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 (
|
||||
<SchemaComponentProvider components={{ Input, ArrayTable, FormItem, ArrayTableColumnInitializer }}>
|
||||
<SchemaComponentProvider components={{ Input, ArrayTable, FormItem }}>
|
||||
<SchemaComponent schema={schema} />
|
||||
</SchemaComponentProvider>
|
||||
);
|
||||
|
@ -29,3 +29,4 @@ export * from './time-picker';
|
||||
export * from './tree-select';
|
||||
export * from './upload';
|
||||
export * from './void-table';
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
export * from './useAttach';
|
||||
export * from './useCompile';
|
||||
export * from './useComponent';
|
||||
export * from './useDesignable';
|
||||
export * from './useFieldProps';
|
||||
export * from './useSchemaComponentContext';
|
||||
|
14
packages/client/src/schema-component/hooks/useComponent.ts
Normal file
14
packages/client/src/schema-component/hooks/useComponent.ts
Normal file
@ -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);
|
||||
};
|
@ -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) => {
|
||||
|
@ -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 = (
|
||||
<Menu>
|
||||
@ -22,7 +20,7 @@ SchemaInitializer.Button = observer((props: any) => {
|
||||
return <Menu.Divider key={`item-${indexA}`} />;
|
||||
}
|
||||
if (item.component) {
|
||||
const Component = typeof item.component === 'object' ? item.component : get(components, item.component);
|
||||
const Component = findComponent(item.component);
|
||||
return (
|
||||
Component && (
|
||||
<SchemaInitializerItemContext.Provider
|
||||
@ -53,8 +51,7 @@ SchemaInitializer.Button = observer((props: any) => {
|
||||
if (!child.component) {
|
||||
return null;
|
||||
}
|
||||
const Component =
|
||||
typeof child.component === 'object' ? child.component : get(components, child.component);
|
||||
const Component = findComponent(child.component);
|
||||
return (
|
||||
Component && (
|
||||
<SchemaInitializerItemContext.Provider
|
||||
|
@ -1,34 +1,29 @@
|
||||
import { FormOutlined, TableOutlined } from '@ant-design/icons';
|
||||
import { Field } from '@formily/core';
|
||||
import { observer, useField } from '@formily/react';
|
||||
import { SchemaComponent, SchemaComponentProvider, SchemaInitializer } from '@nocobase/client';
|
||||
import { observer } from '@formily/react';
|
||||
import { Action, ActionBar, SchemaComponent, SchemaComponentProvider, SchemaInitializer } from '@nocobase/client';
|
||||
import React from 'react';
|
||||
|
||||
const Hello = observer((props) => {
|
||||
const field = useField<Field>();
|
||||
return (
|
||||
<div style={{ marginBottom: 20, padding: '0 20px', height: 50, lineHeight: '50px', background: '#f1f1f1' }}>
|
||||
{field.title}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
const InitializerDemo = observer((props: any) => {
|
||||
const InitializerButton = observer((props: any) => {
|
||||
return (
|
||||
<SchemaInitializer.Button
|
||||
wrap={(schema) => 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 (
|
||||
<SchemaInitializer.Item
|
||||
icon={<TableOutlined />}
|
||||
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
|
||||
</SchemaInitializer.Item>
|
||||
);
|
||||
};
|
||||
|
||||
const FormBlockInitializer = (props) => {
|
||||
const { insert } = props;
|
||||
return (
|
||||
<SchemaInitializer.Item
|
||||
icon={<FormOutlined />}
|
||||
onClick={(info) => {
|
||||
insert({
|
||||
type: 'void',
|
||||
title: 'form',
|
||||
'x-component': 'Hello',
|
||||
'x-component': 'Action',
|
||||
...schema,
|
||||
});
|
||||
}}
|
||||
>
|
||||
Form
|
||||
{title}
|
||||
</SchemaInitializer.Item>
|
||||
);
|
||||
};
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
<SchemaComponentProvider components={{ Hello, InitializerDemo, TableBlockInitializer, FormBlockInitializer }}>
|
||||
<SchemaComponentProvider components={{ ActionBar, Action, ActionInitializer, InitializerButton }}>
|
||||
<SchemaComponent
|
||||
schema={{
|
||||
type: 'void',
|
||||
name: 'page',
|
||||
'x-component': 'div',
|
||||
'x-component': 'ActionBar',
|
||||
'x-initializer': 'InitializerButton',
|
||||
properties: {
|
||||
hello1: {
|
||||
action1: {
|
||||
type: 'void',
|
||||
title: 'Test1',
|
||||
'x-component': 'Hello',
|
||||
'x-component': 'Action',
|
||||
},
|
||||
hello2: {
|
||||
action2: {
|
||||
type: 'void',
|
||||
title: 'Test2',
|
||||
'x-component': 'Hello',
|
||||
},
|
||||
initializer: {
|
||||
type: 'void',
|
||||
'x-component': 'InitializerDemo',
|
||||
'x-component': 'Action',
|
||||
},
|
||||
},
|
||||
}}
|
||||
|
@ -1,12 +1,64 @@
|
||||
import {
|
||||
ArrayTable,
|
||||
ArrayTableColumnInitializer,
|
||||
Input,
|
||||
SchemaComponent,
|
||||
SchemaComponentProvider
|
||||
} from '@nocobase/client';
|
||||
import { observer } from '@formily/react';
|
||||
import { ArrayTable, Input, SchemaComponent, SchemaComponentProvider, SchemaInitializer } from '@nocobase/client';
|
||||
import React from 'react';
|
||||
|
||||
const useTableColumnInitializerFields = () => {
|
||||
const fields = [
|
||||
{
|
||||
key: 'field1',
|
||||
title: 'Field1',
|
||||
component: ColumnInitializer,
|
||||
},
|
||||
{
|
||||
key: 'field2',
|
||||
title: 'Field2',
|
||||
component: 'ColumnInitializer',
|
||||
},
|
||||
];
|
||||
return fields;
|
||||
};
|
||||
|
||||
export const InitializerButton = observer((props: any) => {
|
||||
return (
|
||||
<SchemaInitializer.Button
|
||||
wrap={(schema) => schema}
|
||||
insertPosition={'beforeEnd'}
|
||||
items={[
|
||||
{
|
||||
title: 'Display fields',
|
||||
children: useTableColumnInitializerFields(),
|
||||
},
|
||||
]}
|
||||
>
|
||||
Configure columns
|
||||
</SchemaInitializer.Button>
|
||||
);
|
||||
});
|
||||
|
||||
export const ColumnInitializer = (props) => {
|
||||
const { title, insert } = props;
|
||||
return (
|
||||
<SchemaInitializer.Item
|
||||
onClick={(info) => {
|
||||
insert({
|
||||
type: 'void',
|
||||
title: 'Name',
|
||||
'x-component': 'ArrayTable.Column',
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
'x-component': 'Input',
|
||||
'x-read-pretty': true,
|
||||
},
|
||||
},
|
||||
});
|
||||
}}
|
||||
>
|
||||
{title}
|
||||
</SchemaInitializer.Item>
|
||||
);
|
||||
};
|
||||
|
||||
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 (
|
||||
<SchemaComponentProvider components={{ Input, ArrayTable, ArrayTableColumnInitializer }}>
|
||||
<SchemaComponentProvider components={{ ColumnInitializer, Input, ArrayTable, InitializerButton }}>
|
||||
<SchemaComponent schema={schema} />
|
||||
</SchemaComponentProvider>
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user