refactor(DataBlock): form block (#3771)
* refactor: extract to createCreateFormBBlockUISchema * refactor: extract to createEditFormBlockUISchema * refactor: use new function to create UISchema * refactor: add x-use-decorator-props * fix: add withDynamicSchemaProps to FormBlockProvider * chore: update import path for withDynamicSchemaProps * refactor: should not get collection on getting association in UISchema * refactor: use x-use-component-props instead of useProps * fix: fix withDynamicSchemaProps * chore: fix unit test
This commit is contained in:
parent
cfa6930d70
commit
c6922b071d
@ -1,9 +1,14 @@
|
||||
import React from 'react';
|
||||
import { Plugin } from '../application/Plugin';
|
||||
import { ActionSchemaToolbar } from '../modules/actions/ActionSchemaToolbar';
|
||||
import { CollapseItemSchemaToolbar } from '../modules/blocks/filter-blocks/collapse/CollapseItemSchemaToolbar';
|
||||
import { BlockSchemaToolbar } from '../modules/blocks/BlockSchemaToolbar';
|
||||
import { FormItemSchemaToolbar } from '../modules/blocks/data-blocks/form/FormItemSchemaToolbar';
|
||||
import { useCreateFormBlockDecoratorProps } from '../modules/blocks/data-blocks/form/hooks/useCreateFormBlockDecoratorProps';
|
||||
import { useCreateFormBlockProps } from '../modules/blocks/data-blocks/form/hooks/useCreateFormBlockProps';
|
||||
import { useEditFormBlockDecoratorProps } from '../modules/blocks/data-blocks/form/hooks/useEditFormBlockDecoratorProps';
|
||||
import { useEditFormBlockProps } from '../modules/blocks/data-blocks/form/hooks/useEditFormBlockProps';
|
||||
import { TableColumnSchemaToolbar } from '../modules/blocks/data-blocks/table/TableColumnSchemaToolbar';
|
||||
import { CollapseItemSchemaToolbar } from '../modules/blocks/filter-blocks/collapse/CollapseItemSchemaToolbar';
|
||||
import { SchemaComponentOptions } from '../schema-component';
|
||||
import { RecordLink, useParamsFromRecord, useSourceIdFromParentRecord, useSourceIdFromRecord } from './BlockProvider';
|
||||
import { DetailsBlockProvider, useDetailsBlockProps } from './DetailsBlockProvider';
|
||||
@ -15,7 +20,6 @@ import { useTableBlockProps } from '../modules/blocks/data-blocks/table/hooks/us
|
||||
import { TableFieldProvider, useTableFieldProps } from './TableFieldProvider';
|
||||
import { TableSelectorProvider, useTableSelectorProps } from './TableSelectorProvider';
|
||||
import * as bp from './hooks';
|
||||
import { BlockSchemaToolbar } from '../modules/blocks/BlockSchemaToolbar';
|
||||
import { useTableBlockDecoratorProps } from '../modules/blocks/data-blocks/table/hooks/useTableBlockDecoratorProps';
|
||||
|
||||
// TODO: delete this, replaced by `BlockSchemaComponentPlugin`
|
||||
@ -38,6 +42,10 @@ export const BlockSchemaComponentProvider: React.FC = (props) => {
|
||||
useSourceIdFromParentRecord,
|
||||
useParamsFromRecord,
|
||||
useFormBlockProps,
|
||||
useCreateFormBlockProps,
|
||||
useCreateFormBlockDecoratorProps,
|
||||
useEditFormBlockDecoratorProps,
|
||||
useEditFormBlockProps,
|
||||
useFormFieldProps,
|
||||
useDetailsBlockProps,
|
||||
useTableFieldProps,
|
||||
@ -82,6 +90,10 @@ export class BlockSchemaComponentPlugin extends Plugin {
|
||||
useSourceIdFromParentRecord,
|
||||
useParamsFromRecord,
|
||||
useFormBlockProps,
|
||||
useCreateFormBlockProps,
|
||||
useCreateFormBlockDecoratorProps,
|
||||
useEditFormBlockDecoratorProps,
|
||||
useEditFormBlockProps,
|
||||
useFormFieldProps,
|
||||
useDetailsBlockProps,
|
||||
useTableFieldProps,
|
||||
|
@ -10,6 +10,7 @@ import { Templates as DataTemplateSelect } from '../schema-component/antd/form-v
|
||||
import { BlockProvider, useBlockRequestContext } from './BlockProvider';
|
||||
import { TemplateBlockProvider } from './TemplateBlockProvider';
|
||||
import { FormActiveFieldsProvider } from './hooks/useFormActiveFields';
|
||||
import { withDynamicSchemaProps } from '../application/hoc/withDynamicSchemaProps';
|
||||
|
||||
export const FormBlockContext = createContext<{
|
||||
form?: any;
|
||||
@ -29,7 +30,7 @@ FormBlockContext.displayName = 'FormBlockContext';
|
||||
|
||||
const InternalFormBlockProvider = (props) => {
|
||||
const ctx = useFormBlockContext();
|
||||
const { action, readPretty, params, association, collection } = props;
|
||||
const { action, readPretty, params, collection } = props;
|
||||
const field = useField();
|
||||
const form = useMemo(
|
||||
() =>
|
||||
@ -89,7 +90,7 @@ export const useIsDetailBlock = () => {
|
||||
return ctx.type !== 'create' && fieldSchema?.['x-acl-action'] !== 'create' && fieldSchema?.['x-action'] !== 'create';
|
||||
};
|
||||
|
||||
export const FormBlockProvider = (props) => {
|
||||
export const FormBlockProvider = withDynamicSchemaProps((props) => {
|
||||
const record = useRecord();
|
||||
const parentRecordData = useCollectionParentRecordData();
|
||||
const { collection, isCusomeizeCreate } = props;
|
||||
@ -120,7 +121,7 @@ export const FormBlockProvider = (props) => {
|
||||
</BlockProvider>
|
||||
</TemplateBlockProvider>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
export const useFormBlockContext = () => {
|
||||
return useContext(FormBlockContext);
|
||||
|
@ -4,8 +4,9 @@ import React from 'react';
|
||||
import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } from '../../../../application';
|
||||
import { useBlockAssociationContext } from '../../../../block-provider';
|
||||
import { useCollection_deprecated } from '../../../../collection-manager';
|
||||
import { useRecordCollectionDataSourceItems } from '../../../../schema-initializer/utils';
|
||||
import { useSchemaTemplateManager } from '../../../../schema-templates';
|
||||
import { createFormBlockSchema, useRecordCollectionDataSourceItems } from '../../../../schema-initializer/utils';
|
||||
import { createCreateFormBlockUISchema } from './createCreateFormBlockUISchema';
|
||||
|
||||
// TODO: `SchemaInitializerItem` items
|
||||
export const CreateFormBlockInitializer = () => {
|
||||
@ -23,14 +24,19 @@ export const CreateFormBlockInitializer = () => {
|
||||
if (item.template) {
|
||||
const s = await getTemplateSchemaByMode(item);
|
||||
if (item.template.componentName === 'FormItem') {
|
||||
const blockSchema = createFormBlockSchema({
|
||||
actionInitializers: 'createForm:configureActions',
|
||||
const blockSchema = createCreateFormBlockUISchema(
|
||||
association
|
||||
? {
|
||||
association,
|
||||
dataSource: collection.dataSource,
|
||||
collection: collection.name,
|
||||
template: s,
|
||||
settings: 'blockSettings:createForm',
|
||||
});
|
||||
templateSchema: s,
|
||||
}
|
||||
: {
|
||||
collectionName: collection.name,
|
||||
dataSource: collection.dataSource,
|
||||
templateSchema: s,
|
||||
},
|
||||
);
|
||||
if (item.mode === 'reference') {
|
||||
blockSchema['x-template-key'] = item.template.key;
|
||||
}
|
||||
@ -40,13 +46,17 @@ export const CreateFormBlockInitializer = () => {
|
||||
}
|
||||
} else {
|
||||
insert(
|
||||
createFormBlockSchema({
|
||||
actionInitializers: 'createForm:configureActions',
|
||||
createCreateFormBlockUISchema(
|
||||
association
|
||||
? {
|
||||
association,
|
||||
dataSource: collection.dataSource,
|
||||
collection: collection.name,
|
||||
settings: 'blockSettings:createForm',
|
||||
}),
|
||||
}
|
||||
: {
|
||||
collectionName: collection.name,
|
||||
dataSource: collection.dataSource,
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}}
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { FormOutlined } from '@ant-design/icons';
|
||||
import React, { useCallback } from 'react';
|
||||
import { useSchemaInitializer, useSchemaInitializerItem } from '../../../../application';
|
||||
import { createFormBlockSchema } from '../../../../schema-initializer/utils';
|
||||
import { DataBlockInitializer } from '../../../../schema-initializer/items/DataBlockInitializer';
|
||||
import { Collection, CollectionFieldOptions } from '../../../../data-source/collection/Collection';
|
||||
import { DataBlockInitializer } from '../../../../schema-initializer/items/DataBlockInitializer';
|
||||
import { createCreateFormBlockUISchema } from './createCreateFormBlockUISchema';
|
||||
|
||||
export const FormBlockInitializer = ({
|
||||
filterCollections,
|
||||
@ -44,11 +44,10 @@ export const FormBlockInitializer = ({
|
||||
}
|
||||
|
||||
insert(
|
||||
createFormBlockSchema({
|
||||
collection: item.collectionName || item.name,
|
||||
createCreateFormBlockUISchema({
|
||||
collectionName: item.collectionName || item.name,
|
||||
dataSource: item.dataSource,
|
||||
isCusomeizeCreate,
|
||||
settings: 'blockSettings:createForm',
|
||||
}),
|
||||
);
|
||||
},
|
||||
@ -65,12 +64,11 @@ export const FormBlockInitializer = ({
|
||||
return templateWrap(templateSchema, { item });
|
||||
}
|
||||
|
||||
const schema = createFormBlockSchema({
|
||||
const schema = createCreateFormBlockUISchema({
|
||||
isCusomeizeCreate,
|
||||
dataSource: item.dataSource,
|
||||
template: templateSchema,
|
||||
collection: item.name,
|
||||
settings: 'blockSettings:createForm',
|
||||
templateSchema: templateSchema,
|
||||
collectionName: item.name,
|
||||
});
|
||||
if (item.template && item.mode === 'reference') {
|
||||
schema['x-template-key'] = item.template.key;
|
||||
|
@ -3,8 +3,9 @@ import React, { useCallback } from 'react';
|
||||
import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } from '../../../../application';
|
||||
import { useBlockAssociationContext } from '../../../../block-provider';
|
||||
import { useCollection_deprecated } from '../../../../collection-manager';
|
||||
import { useRecordCollectionDataSourceItems } from '../../../../schema-initializer/utils';
|
||||
import { useSchemaTemplateManager } from '../../../../schema-templates';
|
||||
import { createFormBlockSchema, useRecordCollectionDataSourceItems } from '../../../../schema-initializer/utils';
|
||||
import { createEditFormBlockUISchema } from './createEditFormBlockUISchema';
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
@ -43,16 +44,17 @@ export function useCreateEditFormBlock() {
|
||||
const createEditFormBlock = useCallback(
|
||||
({ item }) => {
|
||||
insert(
|
||||
createFormBlockSchema({
|
||||
createEditFormBlockUISchema(
|
||||
association
|
||||
? {
|
||||
association,
|
||||
collection: item.collectionName || item.name,
|
||||
dataSource: item.dataSource,
|
||||
action: 'get',
|
||||
useSourceId: '{{ useSourceIdFromParentRecord }}',
|
||||
useParams: '{{ useParamsFromRecord }}',
|
||||
actionInitializers: 'editForm:configureActions',
|
||||
settings: 'blockSettings:editForm',
|
||||
}),
|
||||
}
|
||||
: {
|
||||
collectionName: item.collectionName || item.name,
|
||||
dataSource: item.dataSource,
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
[association, insert],
|
||||
@ -61,17 +63,19 @@ export function useCreateEditFormBlock() {
|
||||
const templateWrap = useCallback(
|
||||
(templateSchema, { item }) => {
|
||||
if (item.template.componentName === 'FormItem') {
|
||||
const blockSchema = createFormBlockSchema({
|
||||
const blockSchema = createEditFormBlockUISchema(
|
||||
association
|
||||
? {
|
||||
association,
|
||||
collection: item.collectionName || item.name,
|
||||
dataSource: item.dataSource,
|
||||
action: 'get',
|
||||
useSourceId: '{{ useSourceIdFromParentRecord }}',
|
||||
useParams: '{{ useParamsFromRecord }}',
|
||||
actionInitializers: 'editForm:configureActions',
|
||||
template: templateSchema,
|
||||
settings: 'blockSettings:editForm',
|
||||
});
|
||||
templateSchema: templateSchema,
|
||||
}
|
||||
: {
|
||||
collectionName: item.collectionName || item.name,
|
||||
dataSource: item.dataSource,
|
||||
templateSchema: templateSchema,
|
||||
},
|
||||
);
|
||||
if (item.mode === 'reference') {
|
||||
blockSchema['x-template-key'] = item.template.key;
|
||||
}
|
||||
|
@ -0,0 +1,64 @@
|
||||
import { CreateFormBlockUISchemaOptions, createCreateFormBlockUISchema } from '../createCreateFormBlockUISchema';
|
||||
|
||||
vi.mock('@formily/shared', () => {
|
||||
return {
|
||||
uid: () => 'mocked-uid',
|
||||
};
|
||||
});
|
||||
|
||||
describe('createCreateFormBlockUISchema', () => {
|
||||
it('should create a schema with all options', () => {
|
||||
const options: CreateFormBlockUISchemaOptions = {
|
||||
collectionName: 'users',
|
||||
dataSource: 'userDataSource',
|
||||
association: 'userAssociation',
|
||||
templateSchema: { type: 'string' },
|
||||
isCusomeizeCreate: true,
|
||||
};
|
||||
|
||||
const result = createCreateFormBlockUISchema(options);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"properties": {
|
||||
"mocked-uid": {
|
||||
"properties": {
|
||||
"grid": {
|
||||
"type": "string",
|
||||
},
|
||||
"mocked-uid": {
|
||||
"type": "void",
|
||||
"x-component": "ActionBar",
|
||||
"x-component-props": {
|
||||
"layout": "one-column",
|
||||
"style": {
|
||||
"marginTop": 24,
|
||||
},
|
||||
},
|
||||
"x-initializer": "createForm:configureActions",
|
||||
},
|
||||
},
|
||||
"type": "void",
|
||||
"x-component": "FormV2",
|
||||
"x-use-component-props": "useCreateFormBlockProps",
|
||||
},
|
||||
},
|
||||
"type": "void",
|
||||
"x-acl-action": "userAssociation:create",
|
||||
"x-acl-action-props": {
|
||||
"skipScopeCheck": true,
|
||||
},
|
||||
"x-component": "CardItem",
|
||||
"x-decorator": "FormBlockProvider",
|
||||
"x-decorator-props": {
|
||||
"association": "userAssociation",
|
||||
"collection": "users",
|
||||
"dataSource": "userDataSource",
|
||||
"isCusomeizeCreate": true,
|
||||
},
|
||||
"x-settings": "blockSettings:createForm",
|
||||
"x-toolbar": "BlockSchemaToolbar",
|
||||
"x-use-decorator-props": "useCreateFormBlockDecoratorProps",
|
||||
}
|
||||
`);
|
||||
});
|
||||
});
|
@ -0,0 +1,62 @@
|
||||
import { ISchema } from '@formily/react';
|
||||
import { vi } from 'vitest';
|
||||
import { createEditFormBlockUISchema } from '../createEditFormBlockUISchema';
|
||||
|
||||
vi.mock('@formily/shared', () => ({
|
||||
uid: () => 'uniqueId',
|
||||
}));
|
||||
|
||||
describe('createEditFormBlockUISchema', () => {
|
||||
it('should create a schema with all options', () => {
|
||||
const schema = createEditFormBlockUISchema({
|
||||
collectionName: 'users',
|
||||
dataSource: 'UserDataSource',
|
||||
association: 'users:update',
|
||||
templateSchema: { type: 'string' },
|
||||
});
|
||||
|
||||
expect(schema).toMatchInlineSnapshot(`
|
||||
{
|
||||
"properties": {
|
||||
"uniqueId": {
|
||||
"properties": {
|
||||
"grid": {
|
||||
"type": "string",
|
||||
},
|
||||
"uniqueId": {
|
||||
"type": "void",
|
||||
"x-component": "ActionBar",
|
||||
"x-component-props": {
|
||||
"layout": "one-column",
|
||||
"style": {
|
||||
"marginTop": 24,
|
||||
},
|
||||
},
|
||||
"x-initializer": "editForm:configureActions",
|
||||
},
|
||||
},
|
||||
"type": "void",
|
||||
"x-component": "FormV2",
|
||||
"x-use-component-props": "useEditFormBlockProps",
|
||||
},
|
||||
},
|
||||
"type": "void",
|
||||
"x-acl-action": "users:update:update",
|
||||
"x-acl-action-props": {
|
||||
"skipScopeCheck": false,
|
||||
},
|
||||
"x-component": "CardItem",
|
||||
"x-decorator": "FormBlockProvider",
|
||||
"x-decorator-props": {
|
||||
"action": "get",
|
||||
"association": "users:update",
|
||||
"collection": "users",
|
||||
"dataSource": "UserDataSource",
|
||||
},
|
||||
"x-settings": "blockSettings:editForm",
|
||||
"x-toolbar": "BlockSchemaToolbar",
|
||||
"x-use-decorator-props": "useEditFormBlockDecoratorProps",
|
||||
}
|
||||
`);
|
||||
});
|
||||
});
|
@ -0,0 +1,70 @@
|
||||
import { ISchema } from '@formily/react';
|
||||
import { uid } from '@formily/shared';
|
||||
|
||||
export interface CreateFormBlockUISchemaOptions {
|
||||
dataSource: string;
|
||||
/** 如果传了 association 就不需要再传 collectionName 了 */
|
||||
collectionName?: string;
|
||||
association?: string;
|
||||
templateSchema?: ISchema;
|
||||
isCusomeizeCreate?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建新增表单的 UI Schema
|
||||
* @returns
|
||||
*/
|
||||
export function createCreateFormBlockUISchema(options: CreateFormBlockUISchemaOptions): ISchema {
|
||||
const { collectionName, association, dataSource, templateSchema, isCusomeizeCreate } = options;
|
||||
const resourceName = association || collectionName;
|
||||
|
||||
if (!dataSource) {
|
||||
throw new Error('dataSource are required');
|
||||
}
|
||||
|
||||
const schema: ISchema = {
|
||||
type: 'void',
|
||||
'x-acl-action-props': {
|
||||
skipScopeCheck: true,
|
||||
},
|
||||
'x-acl-action': `${resourceName}:create`,
|
||||
'x-decorator': 'FormBlockProvider',
|
||||
'x-use-decorator-props': 'useCreateFormBlockDecoratorProps',
|
||||
'x-decorator-props': {
|
||||
dataSource,
|
||||
collection: collectionName,
|
||||
association,
|
||||
isCusomeizeCreate,
|
||||
},
|
||||
'x-toolbar': 'BlockSchemaToolbar',
|
||||
'x-settings': 'blockSettings:createForm',
|
||||
'x-component': 'CardItem',
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
'x-component': 'FormV2',
|
||||
'x-use-component-props': 'useCreateFormBlockProps',
|
||||
properties: {
|
||||
grid: templateSchema || {
|
||||
type: 'void',
|
||||
'x-component': 'Grid',
|
||||
'x-initializer': 'form:configureFields',
|
||||
properties: {},
|
||||
},
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
'x-initializer': 'createForm:configureActions',
|
||||
'x-component': 'ActionBar',
|
||||
'x-component-props': {
|
||||
layout: 'one-column',
|
||||
style: {
|
||||
marginTop: 24,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
return schema;
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
import { ISchema } from '@formily/react';
|
||||
import { uid } from '@formily/shared';
|
||||
|
||||
interface EditFormBlockOptions {
|
||||
dataSource: string;
|
||||
/** 如果传了 association 就不需要再传 collectionName 了 */
|
||||
collectionName?: string;
|
||||
association?: string;
|
||||
templateSchema?: ISchema;
|
||||
}
|
||||
|
||||
export function createEditFormBlockUISchema(options: EditFormBlockOptions): ISchema {
|
||||
const { collectionName, dataSource, association, templateSchema } = options;
|
||||
const resourceName = association || collectionName;
|
||||
|
||||
if (!dataSource) {
|
||||
throw new Error('dataSource are required');
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'void',
|
||||
'x-acl-action-props': {
|
||||
skipScopeCheck: false,
|
||||
},
|
||||
'x-acl-action': `${resourceName}:update`,
|
||||
'x-decorator': 'FormBlockProvider',
|
||||
'x-use-decorator-props': 'useEditFormBlockDecoratorProps',
|
||||
'x-decorator-props': {
|
||||
action: 'get',
|
||||
dataSource,
|
||||
collection: collectionName,
|
||||
association,
|
||||
},
|
||||
'x-toolbar': 'BlockSchemaToolbar',
|
||||
'x-settings': 'blockSettings:editForm',
|
||||
'x-component': 'CardItem',
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
'x-component': 'FormV2',
|
||||
'x-use-component-props': 'useEditFormBlockProps',
|
||||
properties: {
|
||||
grid: templateSchema || {
|
||||
type: 'void',
|
||||
'x-component': 'Grid',
|
||||
'x-initializer': 'form:configureFields',
|
||||
properties: {},
|
||||
},
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
'x-initializer': 'editForm:configureActions',
|
||||
'x-component': 'ActionBar',
|
||||
'x-component-props': {
|
||||
layout: 'one-column',
|
||||
style: {
|
||||
marginTop: 24,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
import { useFormBlockSourceId } from './useFormBlockSourceId';
|
||||
|
||||
export function useCreateFormBlockDecoratorProps(props) {
|
||||
let sourceId;
|
||||
|
||||
// association 的值是固定不变的,所以这里可以使用 hooks
|
||||
if (props.association) {
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
sourceId = useFormBlockSourceId(props);
|
||||
}
|
||||
|
||||
return {
|
||||
sourceId,
|
||||
};
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
import { useFormBlockProps } from '../../../../../block-provider/FormBlockProvider';
|
||||
|
||||
export function useCreateFormBlockProps() {
|
||||
return useFormBlockProps();
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
import { useParamsFromRecord } from '../../../../../block-provider/BlockProvider';
|
||||
import { useFormBlockSourceId } from './useFormBlockSourceId';
|
||||
|
||||
export function useEditFormBlockDecoratorProps(props) {
|
||||
const params = useFormBlockParams();
|
||||
let sourceId;
|
||||
|
||||
// association 的值是固定不变的,所以这里可以使用 hooks
|
||||
if (props.association) {
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
sourceId = useFormBlockSourceId(props);
|
||||
}
|
||||
|
||||
return {
|
||||
params,
|
||||
sourceId,
|
||||
};
|
||||
}
|
||||
|
||||
function useFormBlockParams() {
|
||||
return useParamsFromRecord();
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
import { useFormBlockProps } from '../../../../../block-provider/FormBlockProvider';
|
||||
|
||||
export function useEditFormBlockProps() {
|
||||
return useFormBlockProps();
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
import { useDataBlockSourceId } from '../../../../../block-provider/hooks/useDataBlockSourceId';
|
||||
|
||||
export function useFormBlockSourceId(props) {
|
||||
return useDataBlockSourceId(props);
|
||||
}
|
@ -1,11 +1,12 @@
|
||||
export * from './createFormBlockSettings';
|
||||
export * from './CreateFormBlockInitializer';
|
||||
export * from './FormBlockInitializer';
|
||||
export * from './FormItemSchemaToolbar';
|
||||
export * from './RecordFormBlockInitializer';
|
||||
export * from './editFormBlockSettings';
|
||||
export * from './createCreateFormBlockUISchema';
|
||||
export * from './createFormActionInitializers';
|
||||
export * from './createFormBlockSettings';
|
||||
export * from './editFormBlockSettings';
|
||||
export * from './fieldSettingsFormItem';
|
||||
export * from './formActionInitializers';
|
||||
export * from './formItemInitializers';
|
||||
export * from './fieldSettingsFormItem';
|
||||
export * from './updateFormActionInitializers';
|
||||
|
@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
import { FormV2 } from '../form-v2';
|
||||
import { useDetailsBlockContext } from '../../../block-provider/DetailsBlockProvider';
|
||||
import _ from 'lodash';
|
||||
import { Empty } from 'antd';
|
||||
import { useDataBlockRequest } from '../../../data-source';
|
||||
|
@ -18,6 +18,7 @@ import { isVariable, REGEX_OF_VARIABLE } from '../../../variables/utils/isVariab
|
||||
import { getInnermostKeyAndValue, getTargetField } from '../../common/utils/uitls';
|
||||
import { useProps } from '../../hooks/useProps';
|
||||
import { collectFieldStateOfLinkageRules, getTempFieldState } from './utils';
|
||||
import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
|
||||
|
||||
export interface FormProps {
|
||||
[key: string]: any;
|
||||
@ -197,10 +198,13 @@ export const Form: React.FC<FormProps> & {
|
||||
FilterDesigner?: any;
|
||||
ReadPrettyDesigner?: any;
|
||||
Templates?: any;
|
||||
} = observer(
|
||||
(props) => {
|
||||
} = withDynamicSchemaProps(
|
||||
observer((props) => {
|
||||
const field = useField<Field>();
|
||||
|
||||
// 新版 UISchema(1.0 之后)中已经废弃了 useProps,这里之所以继续保留是为了兼容旧版的 UISchema
|
||||
const { form, disabled, ...others } = useProps(props);
|
||||
|
||||
const formDisabled = disabled || field.disabled;
|
||||
return (
|
||||
<ConfigProvider componentDisabled={formDisabled}>
|
||||
@ -222,7 +226,7 @@ export const Form: React.FC<FormProps> & {
|
||||
</form>
|
||||
</ConfigProvider>
|
||||
);
|
||||
},
|
||||
}),
|
||||
{ displayName: 'Form' },
|
||||
);
|
||||
|
||||
|
@ -1,10 +1,11 @@
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import { FormOutlined } from '@ant-design/icons';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
|
||||
import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } from '../../application';
|
||||
import { useSchemaTemplateManager } from '../../schema-templates';
|
||||
import { createFormBlockSchema, useRecordCollectionDataSourceItems } from '../utils';
|
||||
import { useCollectionManager_deprecated } from '../../collection-manager';
|
||||
import { createCreateFormBlockUISchema } from '../../modules/blocks/data-blocks/form/createCreateFormBlockUISchema';
|
||||
import { useSchemaTemplateManager } from '../../schema-templates';
|
||||
import { useRecordCollectionDataSourceItems } from '../utils';
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
@ -18,31 +19,18 @@ export const RecordAssociationFormBlockInitializer = () => {
|
||||
const field = itemConfig.field;
|
||||
const collectionName = field.target;
|
||||
const collection = useMemo(() => getCollection(collectionName), [collectionName]);
|
||||
const resource = `${field.collectionName}.${field.name}`;
|
||||
return (
|
||||
<SchemaInitializerItem
|
||||
icon={<FormOutlined />}
|
||||
{...others}
|
||||
onClick={async ({ item }) => {
|
||||
const action = ['hasOne', 'belongsTo'].includes(field.type) ? 'get' : null;
|
||||
const actionInitializers = ['hasOne', 'belongsTo'].includes(field.type)
|
||||
? 'editForm:configureActions'
|
||||
: 'createForm:configureActions';
|
||||
|
||||
if (item.template) {
|
||||
const template = await getTemplateSchemaByMode(item);
|
||||
if (item.template.componentName === 'FormItem') {
|
||||
const blockSchema = createFormBlockSchema({
|
||||
collection: collectionName,
|
||||
const blockSchema = createCreateFormBlockUISchema({
|
||||
dataSource: collection.dataSource,
|
||||
resource,
|
||||
association: resource,
|
||||
action,
|
||||
useSourceId: '{{ useSourceIdFromParentRecord }}',
|
||||
useParams: '{{ useParamsFromRecord }}',
|
||||
actionInitializers,
|
||||
template: template,
|
||||
settings: 'blockSettings:createForm',
|
||||
association: `${field.collectionName}.${field.name}`,
|
||||
templateSchema: template,
|
||||
});
|
||||
if (item.mode === 'reference') {
|
||||
blockSchema['x-template-key'] = item.template.key;
|
||||
@ -53,21 +41,19 @@ export const RecordAssociationFormBlockInitializer = () => {
|
||||
}
|
||||
} else {
|
||||
insert(
|
||||
createFormBlockSchema({
|
||||
collection: collectionName,
|
||||
resource,
|
||||
createCreateFormBlockUISchema({
|
||||
dataSource: collection.dataSource,
|
||||
association: resource,
|
||||
action,
|
||||
useSourceId: '{{ useSourceIdFromParentRecord }}',
|
||||
useParams: '{{ useParamsFromRecord }}',
|
||||
actionInitializers,
|
||||
settings: 'blockSettings:createForm',
|
||||
association: `${field.collectionName}.${field.name}`,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}}
|
||||
items={useRecordCollectionDataSourceItems('FormItem', itemConfig, collection, resource)}
|
||||
items={useRecordCollectionDataSourceItems(
|
||||
'FormItem',
|
||||
itemConfig,
|
||||
collection,
|
||||
`${field.collectionName}.${field.name}`,
|
||||
)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@ -80,21 +66,11 @@ export function useCreateAssociationFormBlock() {
|
||||
({ item }) => {
|
||||
const field = item.associationField;
|
||||
const collection = getCollection(field.target);
|
||||
const action = ['hasOne', 'belongsTo'].includes(field.type) ? 'get' : null;
|
||||
const actionInitializers = ['hasOne', 'belongsTo'].includes(field.type)
|
||||
? 'editForm:configureActions'
|
||||
: 'createForm:configureActions';
|
||||
|
||||
insert(
|
||||
createFormBlockSchema({
|
||||
collection: field.target,
|
||||
createCreateFormBlockUISchema({
|
||||
dataSource: collection.dataSource,
|
||||
association: `${field.collectionName}.${field.name}`,
|
||||
action,
|
||||
useSourceId: '{{ useSourceIdFromParentRecord }}',
|
||||
useParams: '{{ useParamsFromRecord }}',
|
||||
actionInitializers,
|
||||
settings: 'blockSettings:createForm',
|
||||
}),
|
||||
);
|
||||
},
|
||||
@ -104,23 +80,13 @@ export function useCreateAssociationFormBlock() {
|
||||
const templateWrap = useCallback(
|
||||
(templateSchema, { item }) => {
|
||||
const field = item.associationField;
|
||||
const action = ['hasOne', 'belongsTo'].includes(field.type) ? 'get' : null;
|
||||
const collection = getCollection(field.target);
|
||||
const actionInitializers = ['hasOne', 'belongsTo'].includes(field.type)
|
||||
? 'editForm:configureActions'
|
||||
: 'createForm:configureActions';
|
||||
|
||||
if (item.template.componentName === 'FormItem') {
|
||||
const blockSchema = createFormBlockSchema({
|
||||
collection: field.target,
|
||||
const blockSchema = createCreateFormBlockUISchema({
|
||||
dataSource: collection.dataSource,
|
||||
association: `${field.collectionName}.${field.name}`,
|
||||
action,
|
||||
useSourceId: '{{ useSourceIdFromParentRecord }}',
|
||||
useParams: '{{ useParamsFromRecord }}',
|
||||
actionInitializers,
|
||||
template: templateSchema,
|
||||
settings: 'blockSettings:createForm',
|
||||
templateSchema: templateSchema,
|
||||
});
|
||||
if (item.mode === 'reference') {
|
||||
blockSchema['x-template-key'] = item.template.key;
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { Field, Form } from '@formily/core';
|
||||
import { ISchema, Schema, useFieldSchema, useForm } from '@formily/react';
|
||||
import { uid } from '@formily/shared';
|
||||
import _ from 'lodash';
|
||||
import { useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
@ -12,13 +13,12 @@ import {
|
||||
useFormActiveFields,
|
||||
useFormBlockContext,
|
||||
} from '../';
|
||||
import { FieldOptions, useCollection_deprecated, useCollectionManager_deprecated } from '../collection-manager';
|
||||
import { FieldOptions, useCollectionManager_deprecated, useCollection_deprecated } from '../collection-manager';
|
||||
import { Collection, CollectionFieldOptions } from '../data-source/collection/Collection';
|
||||
import { useDataSourceManager } from '../data-source/data-source/DataSourceManagerProvider';
|
||||
import { isAssocField } from '../filter-provider/utils';
|
||||
import { useActionContext, useCompile, useDesignable } from '../schema-component';
|
||||
import { useSchemaTemplateManager } from '../schema-templates';
|
||||
import { Collection, CollectionFieldOptions } from '../data-source/collection/Collection';
|
||||
import { useDataSourceManager } from '../data-source/data-source/DataSourceManagerProvider';
|
||||
import _ from 'lodash';
|
||||
|
||||
export const itemsMerge = (items1) => {
|
||||
return items1;
|
||||
@ -1150,7 +1150,28 @@ export const createGridCardBlockSchema = (options) => {
|
||||
};
|
||||
return schema;
|
||||
};
|
||||
export const createFormBlockSchema = (options) => {
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* 已弃用,请使用 createCreateFormBlockUISchema 或者 createEditFormBlockUISchema 替代
|
||||
* @param options
|
||||
* @returns
|
||||
*/
|
||||
export const createFormBlockSchema = (options: {
|
||||
formItemInitializers?: string;
|
||||
actionInitializers?: string;
|
||||
collection: string;
|
||||
resource?: string;
|
||||
dataSource?: string;
|
||||
association?: string;
|
||||
action?: string;
|
||||
actions?: Record<string, any>;
|
||||
template?: any;
|
||||
title?: string;
|
||||
settings?: any;
|
||||
'x-designer'?: string;
|
||||
[key: string]: any;
|
||||
}) => {
|
||||
const {
|
||||
formItemInitializers = 'form:configureFields',
|
||||
actionInitializers = 'createForm:configureActions',
|
||||
|
@ -1,15 +1,16 @@
|
||||
import { FormOutlined } from '@ant-design/icons';
|
||||
import React from 'react';
|
||||
import {
|
||||
SchemaInitializerItem,
|
||||
createCreateFormBlockUISchema,
|
||||
useBlockAssociationContext,
|
||||
useCollection_deprecated,
|
||||
useSchemaTemplateManager,
|
||||
createFormBlockSchema,
|
||||
useRecordCollectionDataSourceItems,
|
||||
SchemaInitializerItem,
|
||||
useSchemaInitializer,
|
||||
useSchemaInitializerItem,
|
||||
useSchemaTemplateManager,
|
||||
} from '@nocobase/client';
|
||||
import React from 'react';
|
||||
import { createBulkEditBlockUISchema } from './createBulkEditBlockUISchema';
|
||||
|
||||
export const CreateFormBulkEditBlockInitializer = () => {
|
||||
const itemConfig = useSchemaInitializerItem();
|
||||
@ -26,13 +27,19 @@ export const CreateFormBulkEditBlockInitializer = () => {
|
||||
if (item.template) {
|
||||
const s = await getTemplateSchemaByMode(item);
|
||||
if (item.template.componentName === 'FormItem') {
|
||||
const blockSchema = createFormBlockSchema({
|
||||
actionInitializers: 'createForm:configureActions',
|
||||
const blockSchema = createCreateFormBlockUISchema(
|
||||
association
|
||||
? {
|
||||
association,
|
||||
collection: collection.name,
|
||||
dataSource: collection.dataSource,
|
||||
template: s,
|
||||
});
|
||||
templateSchema: s,
|
||||
}
|
||||
: {
|
||||
collectionName: collection.name,
|
||||
dataSource: collection.dataSource,
|
||||
templateSchema: s,
|
||||
},
|
||||
);
|
||||
if (item.mode === 'reference') {
|
||||
blockSchema['x-template-key'] = item.template.key;
|
||||
}
|
||||
@ -42,11 +49,9 @@ export const CreateFormBulkEditBlockInitializer = () => {
|
||||
}
|
||||
} else {
|
||||
insert(
|
||||
createFormBlockSchema({
|
||||
formItemInitializers: 'bulkEditForm:configureFields',
|
||||
actionInitializers: 'bulkEditForm:configureActions',
|
||||
createBulkEditBlockUISchema({
|
||||
association,
|
||||
collection: collection.name,
|
||||
collectionName: collection.name,
|
||||
dataSource: collection.dataSource,
|
||||
}),
|
||||
);
|
||||
|
@ -0,0 +1,65 @@
|
||||
import { ISchema } from '@formily/react';
|
||||
import { uid } from '@formily/shared';
|
||||
|
||||
/**
|
||||
* 创建批量编辑表单的 UI Schema
|
||||
* @returns
|
||||
*/
|
||||
export function createBulkEditBlockUISchema(options: {
|
||||
collectionName: string;
|
||||
dataSource: string;
|
||||
association?: string;
|
||||
}): ISchema {
|
||||
const { collectionName, association, dataSource } = options;
|
||||
const resourceName = association || collectionName;
|
||||
|
||||
if (!collectionName || !dataSource) {
|
||||
throw new Error('collectionName and dataSource are required');
|
||||
}
|
||||
|
||||
const schema: ISchema = {
|
||||
type: 'void',
|
||||
'x-acl-action-props': {
|
||||
skipScopeCheck: true,
|
||||
},
|
||||
'x-acl-action': `${resourceName}:create`,
|
||||
'x-decorator': 'FormBlockProvider',
|
||||
'x-decorator-props': {
|
||||
dataSource,
|
||||
collection: collectionName,
|
||||
association,
|
||||
},
|
||||
'x-toolbar': 'BlockSchemaToolbar',
|
||||
'x-settings': 'blockSettings:createForm',
|
||||
'x-component': 'CardItem',
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
'x-component': 'FormV2',
|
||||
'x-component-props': {
|
||||
useProps: '{{ useCreateFormBlockProps }}',
|
||||
},
|
||||
properties: {
|
||||
grid: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid',
|
||||
'x-initializer': 'bulkEditForm:configureFields',
|
||||
properties: {},
|
||||
},
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
'x-initializer': 'bulkEditForm:configureActions',
|
||||
'x-component': 'ActionBar',
|
||||
'x-component-props': {
|
||||
layout: 'one-column',
|
||||
style: {
|
||||
marginTop: 24,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
return schema;
|
||||
}
|
@ -4,7 +4,6 @@ import {
|
||||
CollectionProvider_deprecated,
|
||||
SchemaInitializerItem,
|
||||
SchemaInitializerItemType,
|
||||
createFormBlockSchema,
|
||||
useRecordCollectionDataSourceItems,
|
||||
useSchemaInitializer,
|
||||
useSchemaInitializerItem,
|
||||
@ -14,6 +13,7 @@ import {
|
||||
import { JOB_STATUS, traverseSchema } from '@nocobase/plugin-workflow/client';
|
||||
|
||||
import { NAMESPACE } from '../../locale';
|
||||
import { createManualFormBlockUISchema } from './createManualFormBlockUISchema';
|
||||
|
||||
function InternalFormBlockInitializer({ schema, ...others }) {
|
||||
const { getTemplateSchemaByMode } = useSchemaTemplateManager();
|
||||
@ -21,7 +21,7 @@ function InternalFormBlockInitializer({ schema, ...others }) {
|
||||
const items = useRecordCollectionDataSourceItems('FormItem') as SchemaInitializerItemType[];
|
||||
async function onConfirm({ item }) {
|
||||
const template = item.template ? await getTemplateSchemaByMode(item) : null;
|
||||
const result = createFormBlockSchema({
|
||||
const result = createManualFormBlockUISchema({
|
||||
actionInitializers: 'workflowManual:form:configureActions',
|
||||
actions: {
|
||||
resolve: {
|
||||
|
@ -0,0 +1,5 @@
|
||||
import { createFormBlockSchema } from '@nocobase/client';
|
||||
|
||||
export function createManualFormBlockUISchema(options) {
|
||||
return createFormBlockSchema(options);
|
||||
}
|
Loading…
Reference in New Issue
Block a user