mirror of
https://github.com/nocobase/nocobase
synced 2024-11-15 10:46:54 +00:00
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:
parent
1f431dc2d6
commit
d668aa0d92
@ -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;
|
||||||
|
@ -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,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -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 {
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -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';
|
||||||
|
@ -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,8 +23,9 @@ interface AvailableFieldInterfacesExclude {
|
|||||||
exclude?: any[];
|
exclude?: any[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
interface CollectionOptions {
|
interface CollectionOptions {
|
||||||
/**
|
/**
|
||||||
* 自动生成 id
|
* 自动生成 id
|
||||||
* @default true
|
* @default true
|
||||||
* */
|
* */
|
||||||
|
@ -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'],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user