mirror of
https://github.com/nocobase/nocobase
synced 2024-11-15 11:56:29 +00:00
refactor: form data template support data scope config (#2229)
* refactor: data template support data scope config * refactor: data template support data scope config * refactor: locale improve * refactor: code improve * refactor: data template config data scope and title field should linkage with collection field * refactor: code improve * refactor: code improve * refactor: code improve * refactor: code improve * refactor: code improve * refactor: locale improve * refactor: locale improve * refactor: code improve
This commit is contained in:
parent
2c8e7b163e
commit
b42e3b4042
@ -708,5 +708,6 @@ export default {
|
|||||||
"Current object":"Current object",
|
"Current object":"Current object",
|
||||||
"Linkage with form fields":"Linkage with form fields",
|
"Linkage with form fields":"Linkage with form fields",
|
||||||
"Allow add new, update and delete actions":"Allow add new, update and delete actions",
|
"Allow add new, update and delete actions":"Allow add new, update and delete actions",
|
||||||
"Date display format":"Date display format"
|
"Date display format":"Date display format",
|
||||||
|
"Assign data scope for the template":"Assign data scope for the template",
|
||||||
};
|
};
|
||||||
|
@ -619,5 +619,6 @@ export default {
|
|||||||
"Current object":"現在のオブジェクト",
|
"Current object":"現在のオブジェクト",
|
||||||
"Linkage with form fields":"フォームデータから連動",
|
"Linkage with form fields":"フォームデータから連動",
|
||||||
"Allow add new, update and delete actions":"削除変更操作の許可",
|
"Allow add new, update and delete actions":"削除変更操作の許可",
|
||||||
"Date display format":"日付表示形式"
|
"Date display format":"日付表示形式",
|
||||||
|
"Assign data scope for the template":"テンプレートのデータ範囲の指定",
|
||||||
}
|
}
|
||||||
|
@ -793,5 +793,6 @@ export default {
|
|||||||
"Linkage with form fields":"从表单字段联动",
|
"Linkage with form fields":"从表单字段联动",
|
||||||
"Failed to load plugin": "插件加载失败",
|
"Failed to load plugin": "插件加载失败",
|
||||||
"Allow add new, update and delete actions":"允许增删改操作",
|
"Allow add new, update and delete actions":"允许增删改操作",
|
||||||
"Date display format":"日期显示格式"
|
"Date display format":"日期显示格式",
|
||||||
|
"Assign data scope for the template":"为模板指定数据范围",
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
import { useFieldSchema } from '@formily/react';
|
import { useFieldSchema } from '@formily/react';
|
||||||
import { error, forEach } from '@nocobase/utils/client';
|
import { error, forEach } from '@nocobase/utils/client';
|
||||||
import { Select } from 'antd';
|
import { Select, Space } from 'antd';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import React, { useCallback, useEffect, useMemo } from 'react';
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useAPIClient } from '../../../api-client';
|
import { useAPIClient } from '../../../api-client';
|
||||||
import { findFormBlock } from '../../../block-provider';
|
import { findFormBlock } from '../../../block-provider';
|
||||||
import { useCollectionManager } from '../../../collection-manager';
|
import { useCollectionManager } from '../../../collection-manager';
|
||||||
import { useDuplicatefieldsContext } from '../../../schema-initializer/components';
|
import { useDuplicatefieldsContext } from '../../../schema-initializer/components';
|
||||||
|
import { compatibleDataId } from '../../../schema-settings/DataTemplates/FormDataTemplates';
|
||||||
import { useToken } from '../__builtins__';
|
import { useToken } from '../__builtins__';
|
||||||
|
import { RemoteSelect } from '../remote-select';
|
||||||
|
|
||||||
export interface ITemplate {
|
export interface ITemplate {
|
||||||
config?: {
|
config?: {
|
||||||
@ -23,9 +25,11 @@ export interface ITemplate {
|
|||||||
key: string;
|
key: string;
|
||||||
title: string;
|
title: string;
|
||||||
collection: string;
|
collection: string;
|
||||||
dataId: number;
|
dataId?: number;
|
||||||
fields: string[];
|
fields: string[];
|
||||||
default?: boolean;
|
default?: boolean;
|
||||||
|
dataScope?: object;
|
||||||
|
titleField?: string;
|
||||||
}[];
|
}[];
|
||||||
/** 是否在 Form 区块显示模板选择器 */
|
/** 是否在 Form 区块显示模板选择器 */
|
||||||
display: boolean;
|
display: boolean;
|
||||||
@ -63,49 +67,38 @@ const useDataTemplates = () => {
|
|||||||
key: 'none',
|
key: 'none',
|
||||||
title: t('None'),
|
title: t('None'),
|
||||||
},
|
},
|
||||||
].concat(items.map<any>((item, i) => ({ key: i, ...item })));
|
].concat(
|
||||||
|
items.map<any>((t, i) => ({
|
||||||
|
key: i,
|
||||||
|
...t,
|
||||||
|
isLeaf: t.dataId !== null && t.dataId !== undefined,
|
||||||
|
titleCollectionField: t?.titleField && getCollectionJoinField(`${t.collection}.${t.titleField}`),
|
||||||
|
})),
|
||||||
|
);
|
||||||
const defaultTemplate = items.find((item) => item.default);
|
const defaultTemplate = items.find((item) => item.default);
|
||||||
return {
|
return {
|
||||||
templates,
|
templates,
|
||||||
display,
|
display,
|
||||||
defaultTemplate,
|
defaultTemplate,
|
||||||
enabled: items.length > 0 && items.every((item) => item.dataId !== undefined),
|
enabled: items.length > 0 && items.every((item) => item.dataId || item.dataScope),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
function filterReferences(obj) {
|
|
||||||
const filteredObj = {};
|
|
||||||
for (const key in obj) {
|
|
||||||
if (typeof obj[key] !== 'object') {
|
|
||||||
filteredObj[key] = obj[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return filteredObj;
|
|
||||||
}
|
|
||||||
export const Templates = ({ style = {}, form }) => {
|
export const Templates = ({ style = {}, form }) => {
|
||||||
const { token } = useToken();
|
const { token } = useToken();
|
||||||
const { templates, display, enabled, defaultTemplate } = useDataTemplates();
|
const { templates, display, enabled, defaultTemplate } = useDataTemplates();
|
||||||
const [value, setValue] = React.useState(defaultTemplate?.key || 'none');
|
const { getCollectionJoinField } = useCollectionManager();
|
||||||
|
const templateOptions = compatibleDataId(templates);
|
||||||
|
const [targetTemplate, setTargetTemplate] = useState(defaultTemplate?.key || 'none');
|
||||||
|
const [targetTemplateData, setTemplateData] = useState(null);
|
||||||
const api = useAPIClient();
|
const api = useAPIClient();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (enabled && defaultTemplate) {
|
if (enabled && defaultTemplate) {
|
||||||
form.__template = true;
|
form.__template = true;
|
||||||
fetchTemplateData(api, defaultTemplate, t)
|
if (defaultTemplate.key === 'duplicate') {
|
||||||
.then((data) => {
|
handleTemplateDataChange(defaultTemplate.dataId, defaultTemplate);
|
||||||
if (form && data) {
|
}
|
||||||
forEach(data, (value, key) => {
|
|
||||||
if (value) {
|
|
||||||
form.values[key] = value;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.error(err);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@ -122,46 +115,69 @@ export const Templates = ({ style = {}, form }) => {
|
|||||||
return { fontSize: token.fontSize, fontWeight: 'bold', whiteSpace: 'nowrap', marginRight: token.marginXS };
|
return { fontSize: token.fontSize, fontWeight: 'bold', whiteSpace: 'nowrap', marginRight: token.marginXS };
|
||||||
}, [token.fontSize, token.marginXS]);
|
}, [token.fontSize, token.marginXS]);
|
||||||
|
|
||||||
const handleChange = useCallback(async (value, option) => {
|
const handleTemplateChange = useCallback(async (value, option) => {
|
||||||
setValue(value);
|
setTargetTemplate(value);
|
||||||
if (option.key !== 'none') {
|
setTemplateData(null);
|
||||||
fetchTemplateData(api, option, t)
|
form?.reset();
|
||||||
.then((data) => {
|
}, []);
|
||||||
if (form && data) {
|
|
||||||
// 切换之前先把之前的数据清空
|
|
||||||
form.reset();
|
|
||||||
form.__template = true;
|
|
||||||
|
|
||||||
forEach(data, (value, key) => {
|
const handleTemplateDataChange: any = useCallback(async (value, option) => {
|
||||||
if (value) {
|
const template = { ...option, dataId: value };
|
||||||
form.values[key] = value;
|
setTemplateData(option);
|
||||||
}
|
fetchTemplateData(api, template, t)
|
||||||
});
|
.then((data) => {
|
||||||
}
|
if (form && data) {
|
||||||
return data;
|
// 切换之前先把之前的数据清空
|
||||||
})
|
form.reset();
|
||||||
.catch((err) => {
|
form.__template = true;
|
||||||
console.error(err);
|
|
||||||
});
|
forEach(data, (value, key) => {
|
||||||
} else {
|
if (value) {
|
||||||
form?.reset();
|
form.values[key] = value;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if (!enabled || !display) {
|
if (!enabled || !display) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
const template = templateOptions?.find((v) => v.key === targetTemplate);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={wrapperStyle}>
|
<div style={wrapperStyle}>
|
||||||
<label style={labelStyle}>{t('Data template')}: </label>
|
<Space wrap>
|
||||||
<Select
|
<label style={labelStyle}>{t('Data template')}: </label>
|
||||||
popupMatchSelectWidth={false}
|
<Select
|
||||||
options={templates}
|
popupMatchSelectWidth={false}
|
||||||
fieldNames={{ label: 'title', value: 'key' }}
|
options={templateOptions}
|
||||||
value={value}
|
fieldNames={{ label: 'title', value: 'key' }}
|
||||||
onChange={handleChange}
|
value={targetTemplate}
|
||||||
/>
|
onChange={handleTemplateChange}
|
||||||
|
/>
|
||||||
|
{targetTemplate !== 'none' && (
|
||||||
|
<RemoteSelect
|
||||||
|
style={{ width: 220 }}
|
||||||
|
fieldNames={{ label: template.titleField, value: 'id' }}
|
||||||
|
target={template?.collection}
|
||||||
|
value={targetTemplateData}
|
||||||
|
objectValue
|
||||||
|
service={{
|
||||||
|
resource: template?.collection,
|
||||||
|
params: {
|
||||||
|
filter: template?.dataScope,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
onChange={(value) => handleTemplateDataChange(value.id, { ...value, ...template })}
|
||||||
|
targetField={getCollectionJoinField(`${template?.collection}.${template.titleField}`)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Space>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -175,7 +191,7 @@ function findDataTemplates(fieldSchema): ITemplate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchTemplateData(api, template: { collection: string; dataId: number; fields: string[] }, t) {
|
export async function fetchTemplateData(api, template: { collection: string; dataId: number; fields: string[] }, t) {
|
||||||
if (template.fields.length === 0) {
|
if (template.fields.length === 0 || !template.dataId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return api
|
return api
|
||||||
|
@ -7,16 +7,11 @@ import React, { useMemo } from 'react';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { mergeFilter } from '../../block-provider';
|
import { mergeFilter } from '../../block-provider';
|
||||||
import { useCollectionManager } from '../../collection-manager';
|
import { useCollectionManager } from '../../collection-manager';
|
||||||
import {
|
import { SchemaComponent, SchemaComponentContext, removeNullCondition } from '../../schema-component';
|
||||||
AssociationSelect,
|
|
||||||
SchemaComponent,
|
|
||||||
SchemaComponentContext,
|
|
||||||
removeNullCondition,
|
|
||||||
} from '../../schema-component';
|
|
||||||
import { ITemplate } from '../../schema-component/antd/form-v2/Templates';
|
import { ITemplate } from '../../schema-component/antd/form-v2/Templates';
|
||||||
import { AsDefaultTemplate } from './components/AsDefaultTemplate';
|
import { AsDefaultTemplate } from './components/AsDefaultTemplate';
|
||||||
import { ArrayCollapse } from './components/DataTemplateTitle';
|
import { ArrayCollapse } from './components/DataTemplateTitle';
|
||||||
import { Designer, getSelectedIdFilter } from './components/Designer';
|
import { getSelectedIdFilter } from './components/Designer';
|
||||||
import { useCollectionState } from './hooks/useCollectionState';
|
import { useCollectionState } from './hooks/useCollectionState';
|
||||||
|
|
||||||
const Tree = connect(
|
const Tree = connect(
|
||||||
@ -27,11 +22,30 @@ const Tree = connect(
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const compatibleDataId = (data, config?) => {
|
||||||
|
return data?.map((v) => {
|
||||||
|
const { dataId, ...others } = v;
|
||||||
|
const obj = { ...others };
|
||||||
|
if (dataId) {
|
||||||
|
obj.dataScope = { $and: [{ id: { $eq: dataId } }] };
|
||||||
|
obj.titleField = obj?.titleField || config?.[v.collection]?.['titleField'] || 'id';
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export const FormDataTemplates = observer(
|
export const FormDataTemplates = observer(
|
||||||
(props: any) => {
|
(props: any) => {
|
||||||
const { useProps, formSchema, designerCtx } = props;
|
const { useProps, formSchema, designerCtx } = props;
|
||||||
const { defaultValues, collectionName } = useProps();
|
const { defaultValues, collectionName } = useProps();
|
||||||
const { collectionList, getEnableFieldTree, getOnLoadData, getOnCheck } = useCollectionState(collectionName);
|
const {
|
||||||
|
collectionList,
|
||||||
|
getEnableFieldTree,
|
||||||
|
getOnLoadData,
|
||||||
|
getOnCheck,
|
||||||
|
getScopeDataSource,
|
||||||
|
useTitleFieldDataSource,
|
||||||
|
} = useCollectionState(collectionName);
|
||||||
const { getCollection, getCollectionField } = useCollectionManager();
|
const { getCollection, getCollectionField } = useCollectionManager();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
@ -39,11 +53,15 @@ export const FormDataTemplates = observer(
|
|||||||
const activeData = useMemo<ITemplate>(
|
const activeData = useMemo<ITemplate>(
|
||||||
() =>
|
() =>
|
||||||
observable(
|
observable(
|
||||||
defaultValues || { items: [], display: true, config: { [collectionName]: { titleField: '', filter: {} } } },
|
{ ...defaultValues, items: compatibleDataId(defaultValues?.items || [], defaultValues?.config) } || {
|
||||||
|
items: [],
|
||||||
|
display: true,
|
||||||
|
config: { [collectionName]: { titleField: '', filter: {} } },
|
||||||
|
},
|
||||||
),
|
),
|
||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
|
console.log(activeData);
|
||||||
const getTargetField = (collectionName: string) => {
|
const getTargetField = (collectionName: string) => {
|
||||||
const collection = getCollection(collectionName);
|
const collection = getCollection(collectionName);
|
||||||
return getCollectionField(
|
return getCollectionField(
|
||||||
@ -63,8 +81,8 @@ export const FormDataTemplates = observer(
|
|||||||
const filter = activeData.config?.[collectionName]?.filter;
|
const filter = activeData.config?.[collectionName]?.filter;
|
||||||
return _.isEmpty(filter) ? {} : removeNullCondition(mergeFilter([filter, getSelectedIdFilter(value)], '$or'));
|
return _.isEmpty(filter) ? {} : removeNullCondition(mergeFilter([filter, getSelectedIdFilter(value)], '$or'));
|
||||||
};
|
};
|
||||||
|
|
||||||
const components = useMemo(() => ({ ArrayCollapse }), []);
|
const components = useMemo(() => ({ ArrayCollapse }), []);
|
||||||
|
|
||||||
const scope = useMemo(
|
const scope = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
getEnableFieldTree,
|
getEnableFieldTree,
|
||||||
@ -75,6 +93,8 @@ export const FormDataTemplates = observer(
|
|||||||
getOnLoadData,
|
getOnLoadData,
|
||||||
getOnCheck,
|
getOnCheck,
|
||||||
collectionName,
|
collectionName,
|
||||||
|
getScopeDataSource,
|
||||||
|
useTitleFieldDataSource,
|
||||||
}),
|
}),
|
||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
@ -117,49 +137,39 @@ export const FormDataTemplates = observer(
|
|||||||
options: collectionList,
|
options: collectionList,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
dataId: {
|
dataScope: {
|
||||||
type: 'number',
|
type: 'object',
|
||||||
title: '{{ t("Template Data") }}',
|
title: '{{ t("Assign data scope for the template") }}',
|
||||||
required: true,
|
|
||||||
description: t('Select an existing piece of data as the initialization data for the form'),
|
|
||||||
'x-designer': Designer,
|
|
||||||
'x-designer-props': {
|
|
||||||
formSchema,
|
|
||||||
data: activeData,
|
|
||||||
},
|
|
||||||
'x-decorator': 'FormItem',
|
'x-decorator': 'FormItem',
|
||||||
'x-component': AssociationSelect,
|
'x-component': 'Filter',
|
||||||
'x-component-props': {
|
'x-decorator-props': {
|
||||||
service: {
|
style: {
|
||||||
resource: '{{ $record.collection || collectionName }}',
|
marginBottom: '0px',
|
||||||
params: {
|
|
||||||
filter: '{{ getFilter($self.componentProps.service.resource, $self.value) }}',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
action: 'list',
|
|
||||||
multiple: false,
|
|
||||||
objectValue: false,
|
|
||||||
manual: false,
|
|
||||||
targetField: '{{ getTargetField($self.componentProps.service.resource) }}',
|
|
||||||
mapOptions: getMapOptions(),
|
|
||||||
fieldNames: '{{ getFieldNames($self.componentProps.service.resource) }}',
|
|
||||||
},
|
},
|
||||||
|
required: true,
|
||||||
'x-reactions': [
|
'x-reactions': [
|
||||||
{
|
{
|
||||||
dependencies: ['.collection'],
|
dependencies: ['.collection'],
|
||||||
fulfill: {
|
fulfill: {
|
||||||
state: {
|
state: {
|
||||||
disabled: '{{ !$deps[0] }}',
|
disabled: '{{ !$deps[0] }}',
|
||||||
componentProps: {
|
},
|
||||||
service: {
|
schema: {
|
||||||
resource: '{{ getResource($deps[0], $self) }}',
|
enum: '{{ getScopeDataSource($deps[0]) }}',
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
titleField: {
|
||||||
|
type: 'string',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
title: '{{ t("Title field") }}',
|
||||||
|
'x-component': 'Select',
|
||||||
|
required: true,
|
||||||
|
'x-reactions': '{{useTitleFieldDataSource}}',
|
||||||
|
},
|
||||||
fields: {
|
fields: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
title: '{{ t("Data fields") }}',
|
title: '{{ t("Data fields") }}',
|
||||||
@ -246,15 +256,6 @@ export function getLabel(titleField) {
|
|||||||
return titleField || 'label';
|
return titleField || 'label';
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMapOptions() {
|
|
||||||
return (option) => {
|
|
||||||
if (option?.id === undefined) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return option;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getResource(resource: string, field: Field) {
|
function getResource(resource: string, field: Field) {
|
||||||
if (resource !== field.componentProps.service.resource) {
|
if (resource !== field.componentProps.service.resource) {
|
||||||
// 切换 collection 后,之前选中的其它 collection 的数据就没有意义了,需要清空
|
// 切换 collection 后,之前选中的其它 collection 的数据就没有意义了,需要清空
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import { ArrayField } from '@formily/core';
|
import { ArrayField } from '@formily/core';
|
||||||
import React, { useCallback, useState } from 'react';
|
import React, { useCallback, useState } from 'react';
|
||||||
import { useCollectionManager } from '../../../collection-manager';
|
import { useCollectionManager } from '../../../collection-manager';
|
||||||
|
import { isTitleField } from '../../../collection-manager/Configuration/CollectionFields';
|
||||||
import { useCompile } from '../../../schema-component';
|
import { useCompile } from '../../../schema-component';
|
||||||
import { TreeNode } from '../TreeLabel';
|
import { TreeNode } from '../TreeLabel';
|
||||||
|
|
||||||
export const useCollectionState = (currentCollectionName: string) => {
|
export const useCollectionState = (currentCollectionName: string) => {
|
||||||
const { getCollectionFields, getAllCollectionsInheritChain, getCollection } = useCollectionManager();
|
const { getCollectionFields, getAllCollectionsInheritChain, getCollection, getInterface } = useCollectionManager();
|
||||||
const [collectionList] = useState(getCollectionList);
|
const [collectionList] = useState(getCollectionList);
|
||||||
const compile = useCompile();
|
const compile = useCompile();
|
||||||
|
|
||||||
@ -150,11 +151,78 @@ export const useCollectionState = (currentCollectionName: string) => {
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const getScopeDataSource = (resource: string) => {
|
||||||
|
const fields = getCollectionFields(resource);
|
||||||
|
const field2option = (field, depth) => {
|
||||||
|
if (!field.interface) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const fieldInterface = getInterface(field.interface);
|
||||||
|
if (!fieldInterface?.filterable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { nested, children, operators } = fieldInterface.filterable;
|
||||||
|
const option = {
|
||||||
|
name: field.name,
|
||||||
|
title: field?.uiSchema?.title || field.name,
|
||||||
|
schema: field?.uiSchema,
|
||||||
|
operators:
|
||||||
|
operators?.filter?.((operator) => {
|
||||||
|
return !operator?.visible || operator.visible(field);
|
||||||
|
}) || [],
|
||||||
|
interface: field.interface,
|
||||||
|
};
|
||||||
|
if (field.target && depth > 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (depth > 2) {
|
||||||
|
return option;
|
||||||
|
}
|
||||||
|
if (children?.length) {
|
||||||
|
option['children'] = children;
|
||||||
|
}
|
||||||
|
if (nested) {
|
||||||
|
const targetFields = getCollectionFields(field.target);
|
||||||
|
const options = getOptions(targetFields, depth + 1).filter(Boolean);
|
||||||
|
option['children'] = option['children'] || [];
|
||||||
|
option['children'].push(...options);
|
||||||
|
}
|
||||||
|
return option;
|
||||||
|
};
|
||||||
|
const getOptions = (fields, depth) => {
|
||||||
|
const options = [];
|
||||||
|
fields.forEach((field) => {
|
||||||
|
const option = field2option(field, depth);
|
||||||
|
if (option) {
|
||||||
|
options.push(option);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return options;
|
||||||
|
};
|
||||||
|
const options = getOptions(fields, 1);
|
||||||
|
return options;
|
||||||
|
};
|
||||||
|
const useTitleFieldDataSource = (field) => {
|
||||||
|
const fieldPath = field.path.entire.replace('titleField', 'collection');
|
||||||
|
const collectionName = field.query(fieldPath).get('value');
|
||||||
|
const targetFields = getCollectionFields(collectionName);
|
||||||
|
const options = targetFields
|
||||||
|
.filter((field) => {
|
||||||
|
return !field.isForeignKey && getInterface(field.interface)?.titleUsable;
|
||||||
|
})
|
||||||
|
.map((field) => ({
|
||||||
|
value: field?.name,
|
||||||
|
label: compile(field?.uiSchema?.title) || field?.name,
|
||||||
|
}));
|
||||||
|
field.dataSource = options;
|
||||||
|
};
|
||||||
return {
|
return {
|
||||||
collectionList,
|
collectionList,
|
||||||
getEnableFieldTree,
|
getEnableFieldTree,
|
||||||
getOnLoadData,
|
getOnLoadData,
|
||||||
getOnCheck,
|
getOnCheck,
|
||||||
|
getScopeDataSource,
|
||||||
|
useTitleFieldDataSource,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user