feat: configurable the scope of target collections (#1165)

* feat: collection template support availableTargetCollections

* feat: add targetScope

* feat: code opmization

* feat: custom-collection-template improve

* feat: useAsyncDataSource fix

* feat: useAsyncDataSource fix
This commit is contained in:
katherinehhh 2022-12-01 14:24:35 +08:00 committed by GitHub
parent 1f431dc2d6
commit d668aa0d92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 87 additions and 35 deletions

View File

@ -28,7 +28,7 @@ const getSchema = (schema, record: any, compile): ISchema => {
properties['defaultValue']['x-decorator'] = 'FormItem'; properties['defaultValue']['x-decorator'] = 'FormItem';
} }
const initialValue: any = { const initialValue: any = {
name: `f_${uid()}`, name: `t_${uid()}`,
template: schema.name, template: schema.name,
...cloneDeep(schema.default), ...cloneDeep(schema.default),
}; };
@ -198,7 +198,6 @@ const useCreateCollection = () => {
await form.submit(); await form.submit();
const values = cloneDeep(form.values); const values = cloneDeep(form.values);
const fields = useDefaultCollectionFields(values); const fields = useDefaultCollectionFields(values);
console.log(fields);
if (values.autoCreateReverseField) { if (values.autoCreateReverseField) {
} else { } else {
delete values.reverseField; delete values.reverseField;

View File

@ -28,7 +28,6 @@ const getSchema = (schema: IField, record: any, compile) => {
properties['defaultValue']['title'] = compile('{{ t("Default value") }}'); properties['defaultValue']['title'] = compile('{{ t("Default value") }}');
properties['defaultValue']['x-decorator'] = 'FormItem'; properties['defaultValue']['x-decorator'] = 'FormItem';
} }
const initialValue: any = { const initialValue: any = {
name: `f_${uid()}`, name: `f_${uid()}`,
...cloneDeep(schema.default), ...cloneDeep(schema.default),
@ -145,6 +144,7 @@ export const AddFieldAction = (props) => {
const { scope, getContainer, item: record, children, trigger, align } = props; const { scope, getContainer, item: record, children, trigger, align } = props;
const { getInterface, getTemplate } = useCollectionManager(); const { getInterface, getTemplate } = useCollectionManager();
const [visible, setVisible] = useState(false); const [visible, setVisible] = useState(false);
const [targetScope, setTargetScope] = useState();
const [schema, setSchema] = useState({}); const [schema, setSchema] = useState({});
const compile = useCompile(); const compile = useCompile();
const { t } = useTranslation(); const { t } = useTranslation();
@ -165,18 +165,28 @@ export const AddFieldAction = (props) => {
}), }),
}); });
} else { } else {
const children = v.children.filter((v) => { let children = [];
if (include?.length) { if (include?.length) {
return include.includes(v.value); include.forEach((k) => {
} else if (exclude?.length) { const field = v.children.find((h) => [k, k.interface].includes(h.value));
field &&
children.push({
...field,
targetScope: k?.targetScope,
});
});
} else if (exclude?.length) {
children = v.children.filter((v) => {
return !exclude.includes(v.value); return !exclude.includes(v.value);
} });
return true; } else {
}); children = v.children;
optionArr.push({ }
...v, children.length &&
children, optionArr.push({
}); ...v,
children,
});
} }
}); });
return optionArr; return optionArr;
@ -194,8 +204,11 @@ export const AddFieldAction = (props) => {
maxHeight: '60vh', maxHeight: '60vh',
overflow: 'auto', overflow: 'auto',
}} }}
onClick={(info) => { onClick={(e) => {
const schema = getSchema(getInterface(info.key), record, compile); //@ts-ignore
const targetScope = e.item.props['data-targetScope'];
targetScope && setTargetScope(targetScope);
const schema = getSchema(getInterface(e.key), record, compile);
if (schema) { if (schema) {
setSchema(schema); setSchema(schema);
setVisible(true); setVisible(true);
@ -209,7 +222,11 @@ export const AddFieldAction = (props) => {
{option.children {option.children
.filter((child) => !['o2o', 'subTable'].includes(child.name)) .filter((child) => !['o2o', 'subTable'].includes(child.name))
.map((child) => { .map((child) => {
return <Menu.Item key={child.name}>{compile(child.title)}</Menu.Item>; return (
<Menu.Item key={child.name} data-targetScope={child.targetScope}>
{compile(child.title)}
</Menu.Item>
);
})} })}
</Menu.ItemGroup> </Menu.ItemGroup>
) )
@ -234,6 +251,7 @@ export const AddFieldAction = (props) => {
useCreateCollectionField, useCreateCollectionField,
record, record,
showReverseFieldConfig: true, showReverseFieldConfig: true,
targetScope,
...scope, ...scope,
}} }}
/> />

View File

@ -3,7 +3,7 @@ import { ArrayField, Field } from '@formily/core';
import { observer, RecursionField, Schema, useField, useFieldSchema } from '@formily/react'; import { observer, RecursionField, Schema, useField, useFieldSchema } from '@formily/react';
import { Table, TableColumnProps } from 'antd'; import { Table, TableColumnProps } from 'antd';
import { default as classNames } from 'classnames'; import { default as classNames } from 'classnames';
import React, { useState, useRef } from 'react'; import React, { useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { findIndex } from 'lodash'; import { findIndex } from 'lodash';
import { import {

View File

@ -14,14 +14,16 @@ import { FieldSummary } from './components/FieldSummary';
import { EditSubFieldAction } from './EditSubFieldAction'; import { EditSubFieldAction } from './EditSubFieldAction';
import { collectionSchema } from './schemas/collections'; import { collectionSchema } from './schemas/collections';
const useAsyncDataSource = (service: any) => (field: any) => { const useAsyncDataSource = (service: any) => {
field.loading = true; return (field: any, options?: any) => {
service(field).then( field.loading = true;
action.bound((data: any) => { service(field, options).then(
field.dataSource = data; action.bound((data: any) => {
field.loading = false; field.dataSource = data;
}), field.loading = false;
); }),
);
};
}; };
const useSelectedRowKeys = () => { const useSelectedRowKeys = () => {
@ -77,9 +79,15 @@ export const ConfigurationTable = () => {
const collectonsRef: any = useRef(); const collectonsRef: any = useRef();
collectonsRef.current = collections; collectonsRef.current = collections;
const compile = useCompile(); const compile = useCompile();
const loadCollections = async (field: any) => { const loadCollections = async (field, options) => {
const { targetScope } = options;
return collectonsRef.current return collectonsRef.current
?.filter((item) => !(item.autoCreate && item.isThrough)) ?.filter((item) => !(item.autoCreate && item.isThrough))
.filter((item) =>
targetScope
? targetScope['template']?.includes(item.template) || targetScope['name']?.includes(item.name)
: true,
)
.map((item: any) => ({ .map((item: any) => ({
label: compile(item.title), label: compile(item.title),
value: item.name, value: item.name,

View File

@ -128,12 +128,18 @@ const getIsOverriding = (currentFields, record) => {
}; };
export const OverridingFieldAction = (props) => { export const OverridingFieldAction = (props) => {
const { scope, getContainer, item: record, children, currentCollection } = props; const { scope, getContainer, item: record, children, currentCollection } = props;
const { getInterface, getCurrentCollectionFields } = useCollectionManager(); const { target } = record;
const { getInterface, getCurrentCollectionFields, getChildrenCollections } = useCollectionManager();
const [visible, setVisible] = useState(false); const [visible, setVisible] = useState(false);
const [schema, setSchema] = useState({}); const [schema, setSchema] = useState({});
const api = useAPIClient(); const api = useAPIClient();
const { t } = useTranslation(); const { t } = useTranslation();
const compile = useCompile(); const compile = useCompile();
const childCollections =
target &&
getChildrenCollections(target)
?.map((v) => v.name)
.concat([target]);
const [data, setData] = useState<any>({}); const [data, setData] = useState<any>({});
const currentFields = getCurrentCollectionFields(currentCollection); const currentFields = getCurrentCollectionFields(currentCollection);
const disabled = getIsOverriding(currentFields, record); const disabled = getIsOverriding(currentFields, record);
@ -183,6 +189,7 @@ export const OverridingFieldAction = (props) => {
useCancelAction, useCancelAction,
showReverseFieldConfig: !data?.reverseField, showReverseFieldConfig: !data?.reverseField,
createOnly: true, createOnly: true,
targetScope: { name: childCollections },
...scope, ...scope,
}} }}
/> />

View File

@ -1,5 +1,5 @@
import { ArrayTable } from '@formily/antd'; import { ArrayTable } from '@formily/antd';
import { ISchema, useForm } from '@formily/react'; import { ISchema } from '@formily/react';
import { uid } from '@formily/shared'; import { uid } from '@formily/shared';
import cloneDeep from 'lodash/cloneDeep'; import cloneDeep from 'lodash/cloneDeep';
import set from 'lodash/set'; import set from 'lodash/set';

View File

@ -1,12 +1,10 @@
import { ISchema } from '@formily/react'; import { ISchema } from '@formily/react';
import { FieldOptions } from '../../collection-manager/types'; import { FieldOptions } from '../../collection-manager/types';
export interface ICollectionTemplate { export interface ICollectionTemplate {
name: string; name: string;
title?: string; title?: string;
color?:string; color?: string;
/** 排序 */ /** 排序 */
order?: number; order?: number;
/** 默认配置 */ /** 默认配置 */
@ -25,6 +23,7 @@ interface AvailableFieldInterfacesExclude {
exclude?: any[]; exclude?: any[];
} }
interface CollectionOptions { interface CollectionOptions {
/** /**
* id * id

View File

@ -18,9 +18,30 @@ const myCollectionTemplate: ICollectionTemplate = {
}, },
], ],
}, },
configurableProperties: getConfigurableProperties('name', 'title', 'inherits', 'createdAt', 'updatedAt'), configurableProperties: getConfigurableProperties('title', 'name', 'inherits', 'createdAt', 'updatedAt'),
availableFieldInterfaces: { availableFieldInterfaces: {
exclude: ['linkTo', 'o2o'], include: [
'input',
{
interface: 'o2m',
targetScope: {
template: ['calendar'],
},
},
{
interface: 'm2m',
targetScope: {
template: ['calendar', 'myCollection'],
},
},
{
interface: 'linkTo',
targetScope: {
template: ['myCollection'],
},
},
],
// exclude: ['input', 'linkTo'],
}, },
}; };