mirror of
https://github.com/nocobase/nocobase.git
synced 2026-08-29 02:03:53 +08:00
fix(client-v2): default tree filters to cascader (#10357)
This commit is contained in:
@@ -81,6 +81,11 @@ export class FilterFormGridModel extends GridModel {
|
||||
return key;
|
||||
};
|
||||
|
||||
const fieldModelValueKey = normalizeKey(subModel.subModels?.field?.props?.fieldNames?.value);
|
||||
if (fieldModelValueKey) {
|
||||
return fieldModelValueKey;
|
||||
}
|
||||
|
||||
const filterTargetKey = normalizeKey(field?.targetCollection?.filterTargetKey);
|
||||
const fieldTargetKey = normalizeKey(field?.targetKey);
|
||||
|
||||
|
||||
@@ -899,10 +899,13 @@ FilterFormItemModel.registerFlow({
|
||||
type: 'select',
|
||||
key: 'use',
|
||||
props: {
|
||||
options: classes.map((model) => ({
|
||||
label: t(model.modelName),
|
||||
value: model.modelName,
|
||||
})),
|
||||
options: classes.map((model) => {
|
||||
const ModelClass = ctx.engine.getModelClass(model.modelName);
|
||||
return {
|
||||
label: t(ModelClass?.meta?.label || model.modelName),
|
||||
value: model.modelName,
|
||||
};
|
||||
}),
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
+67
@@ -15,6 +15,7 @@ import { FilterFormItemModel } from '../FilterFormItemModel';
|
||||
import { FilterFormGridModel } from '../FilterFormGridModel';
|
||||
import { InputFieldModel } from '../../../fields/InputFieldModel';
|
||||
import { NumberFieldModel } from '../../../fields/NumberFieldModel';
|
||||
import { CascadeSelectFieldModel } from '../../../fields/AssociationFieldModel/CascadeSelectFieldModel';
|
||||
import { RecordSelectFieldModel } from '../../../fields/AssociationFieldModel/RecordSelectFieldModel';
|
||||
import { FilterFormRecordSelectFieldModel } from '../fields/FilterFormRecordSelectFieldModel';
|
||||
|
||||
@@ -42,6 +43,7 @@ function createEngine() {
|
||||
DummyCollectionBlockModel,
|
||||
InputFieldModel,
|
||||
NumberFieldModel,
|
||||
CascadeSelectFieldModel,
|
||||
RecordSelectFieldModel,
|
||||
FilterFormRecordSelectFieldModel,
|
||||
});
|
||||
@@ -83,6 +85,7 @@ function createFilterItemModel(
|
||||
dataBlockModel: DummyCollectionBlockModel,
|
||||
fieldPath: string,
|
||||
fieldModel?: string,
|
||||
fieldProps?: Record<string, unknown>,
|
||||
) {
|
||||
const subModel = engine.createModel<FilterFormItemModel>({
|
||||
uid: `filter-item-${fieldPath}`,
|
||||
@@ -105,6 +108,7 @@ function createFilterItemModel(
|
||||
? {
|
||||
field: {
|
||||
use: fieldModel,
|
||||
props: fieldProps,
|
||||
},
|
||||
}
|
||||
: undefined,
|
||||
@@ -350,4 +354,67 @@ describe('FilterFormGridModel onModelCreated', () => {
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('uses the Cascader value key for both the filter value and connected field path', async () => {
|
||||
const engine = createEngine();
|
||||
const ds = engine.dataSourceManager.getDataSource('main');
|
||||
|
||||
ds.addCollection({
|
||||
name: 'organizations',
|
||||
template: 'tree',
|
||||
filterTargetKey: 'id',
|
||||
fields: [
|
||||
{ name: 'id', type: 'integer', interface: 'number', filterable: { operators: [] } },
|
||||
{ name: 'code', type: 'string', interface: 'input', filterable: { operators: [] } },
|
||||
{ name: 'name', type: 'string', interface: 'input', filterable: { operators: [] } },
|
||||
],
|
||||
});
|
||||
ds.addCollection({
|
||||
name: 'users',
|
||||
filterTargetKey: 'id',
|
||||
fields: [
|
||||
{ name: 'id', type: 'integer', interface: 'number', filterable: { operators: [] } },
|
||||
{
|
||||
name: 'organization',
|
||||
type: 'belongsTo',
|
||||
interface: 'm2o',
|
||||
target: 'organizations',
|
||||
targetKey: 'code',
|
||||
filterable: { operators: [] },
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const dataBlockModel = createDataBlockModel(engine);
|
||||
const { gridModel, saveConnectFieldsConfig } = createGridModel(engine);
|
||||
const subModel = createFilterItemModel(engine, dataBlockModel, 'organization', 'CascadeSelectFieldModel', {
|
||||
fieldNames: { label: 'name', value: 'id' },
|
||||
value: {
|
||||
id: 52,
|
||||
code: 'ORG-52',
|
||||
name: 'Leaf organization',
|
||||
parent: { id: 1, code: 'ORG-1', name: 'Root organization', parent: null },
|
||||
},
|
||||
});
|
||||
subModel.mounted = true;
|
||||
subModel.context.defineProperty('form', {
|
||||
value: {
|
||||
getFieldValue: () => subModel.subModels.field.props.value,
|
||||
},
|
||||
});
|
||||
|
||||
await gridModel.onModelCreated(subModel);
|
||||
|
||||
expect(subModel.getFilterValue()).toBe(52);
|
||||
expect(saveConnectFieldsConfig).toHaveBeenCalledTimes(1);
|
||||
const [, payload] = saveConnectFieldsConfig.mock.calls[0] as unknown as [unknown, unknown];
|
||||
expect(payload).toEqual({
|
||||
targets: [
|
||||
{
|
||||
targetId: dataBlockModel.uid,
|
||||
filterPaths: ['organization.id'],
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+117
@@ -11,6 +11,7 @@ import { describe, expect, it } from 'vitest';
|
||||
import '../../../../index';
|
||||
import { FilterableItemModel, FlowEngine } from '@nocobase/flow-engine';
|
||||
import { CollectionBlockModel } from '../../../base';
|
||||
import { CascadeSelectFieldModel } from '../../../fields/AssociationFieldModel/CascadeSelectFieldModel';
|
||||
import { InputFieldModel } from '../../../fields/InputFieldModel';
|
||||
import { NumberFieldModel } from '../../../fields/NumberFieldModel';
|
||||
import { FilterFormRecordSelectFieldModel } from '../fields/FilterFormRecordSelectFieldModel';
|
||||
@@ -432,6 +433,122 @@ describe('FilterFormItemModel defineChildren association fields', () => {
|
||||
expect(filterItem.subModels.field).toBeInstanceOf(TestCascaderFilterFieldModel);
|
||||
});
|
||||
|
||||
it('uses Cascader by default for tree to-one associations and keeps Dropdown for other associations', async () => {
|
||||
const engine = new FlowEngine();
|
||||
engine.registerModels({
|
||||
FilterFormItemModel: FilterFormItemModel as any,
|
||||
DummyCollectionBlockModel,
|
||||
CascadeSelectFieldModel,
|
||||
FilterFormRecordSelectFieldModel,
|
||||
});
|
||||
|
||||
const ds = engine.dataSourceManager.getDataSource('main');
|
||||
ds?.addCollection({
|
||||
name: 'organizations',
|
||||
template: 'tree',
|
||||
filterTargetKey: 'id',
|
||||
titleField: 'name',
|
||||
fields: [
|
||||
{ name: 'id', type: 'integer', interface: 'number', filterable: { operators: [] } },
|
||||
{ name: 'name', type: 'string', interface: 'input', filterable: { operators: [] } },
|
||||
],
|
||||
});
|
||||
ds?.addCollection({
|
||||
name: 'departments',
|
||||
filterTargetKey: 'id',
|
||||
fields: [
|
||||
{ name: 'id', type: 'integer', interface: 'number', filterable: { operators: [] } },
|
||||
{ name: 'name', type: 'string', interface: 'input', filterable: { operators: [] } },
|
||||
],
|
||||
});
|
||||
ds?.addCollection({
|
||||
name: 'users',
|
||||
filterTargetKey: 'id',
|
||||
fields: [
|
||||
{
|
||||
name: 'organization',
|
||||
title: 'Organization',
|
||||
type: 'belongsTo',
|
||||
interface: 'm2o',
|
||||
target: 'organizations',
|
||||
filterable: { operators: [] },
|
||||
},
|
||||
{
|
||||
name: 'department',
|
||||
title: 'Department',
|
||||
type: 'belongsTo',
|
||||
interface: 'm2o',
|
||||
target: 'departments',
|
||||
filterable: { operators: [] },
|
||||
},
|
||||
{
|
||||
name: 'organizations',
|
||||
title: 'Organizations',
|
||||
type: 'belongsToMany',
|
||||
interface: 'm2m',
|
||||
target: 'organizations',
|
||||
filterable: { operators: [] },
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const model = engine.createModel<DummyCollectionBlockModel>({
|
||||
uid: 'users-tree-association-block',
|
||||
use: 'DummyCollectionBlockModel',
|
||||
stepParams: {
|
||||
resourceSettings: {
|
||||
init: {
|
||||
dataSourceKey: 'main',
|
||||
collectionName: 'users',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const children = (await FilterFormItemModel.defineChildren({
|
||||
blockGridModel: {
|
||||
filterSubModels: (_key: string, predicate: (item: any) => boolean) => [model].filter(predicate),
|
||||
},
|
||||
t: (value: string) => value,
|
||||
} as any)) as any[];
|
||||
const groups = await children[0].children();
|
||||
const fieldsGroup = groups.find((group: any) => group.key === 'fields');
|
||||
const organizationItem = fieldsGroup?.children?.find((item: any) => item.key === 'organization');
|
||||
const departmentItem = fieldsGroup?.children?.find((item: any) => item.key === 'department');
|
||||
const organizationsItem = fieldsGroup?.children?.find((item: any) => item.key === 'organizations');
|
||||
|
||||
const organizationCreateOptions = await organizationItem.createModelOptions();
|
||||
const departmentCreateOptions = await departmentItem.createModelOptions();
|
||||
const organizationsCreateOptions = await organizationsItem.createModelOptions();
|
||||
|
||||
expect(organizationCreateOptions.subModels.field.use).toBe('CascadeSelectFieldModel');
|
||||
expect(organizationCreateOptions.subModels.field.props).toMatchObject({
|
||||
fieldNames: { label: 'name', value: 'id' },
|
||||
});
|
||||
expect(departmentCreateOptions.subModels.field.use).toBe('FilterFormRecordSelectFieldModel');
|
||||
expect(organizationsCreateOptions.subModels.field.use).toBe('FilterFormRecordSelectFieldModel');
|
||||
|
||||
const filterItem = engine.createModel<FilterFormItemModel>({
|
||||
uid: 'filter-item-tree-organization',
|
||||
...organizationCreateOptions,
|
||||
});
|
||||
const modelStep = filterItem.getFlow('filterFormItemSettings')?.steps?.model as any;
|
||||
const settingsContext = {
|
||||
engine,
|
||||
collectionField: ds?.getCollection('users')?.getField('organization'),
|
||||
t: (value: string) => engine.translate(value),
|
||||
};
|
||||
const options = modelStep.uiMode(settingsContext).props.options;
|
||||
|
||||
expect(modelStep.hideInSettings(settingsContext)).not.toBe(true);
|
||||
expect(options).toEqual(
|
||||
expect.arrayContaining([
|
||||
{ label: 'Dropdown select', value: 'FilterFormRecordSelectFieldModel' },
|
||||
{ label: 'Cascader', value: 'CascadeSelectFieldModel' },
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
it('provides fallback field metadata for sql fields without collection context', async () => {
|
||||
const engine = new FlowEngine();
|
||||
engine.registerModels({
|
||||
|
||||
+72
@@ -9,6 +9,8 @@
|
||||
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import '../../../../index';
|
||||
import { FlowEngine } from '@nocobase/flow-engine';
|
||||
import { CascadeSelectFieldModel } from '../../../fields/AssociationFieldModel/CascadeSelectFieldModel';
|
||||
import { FilterFormItemModel } from '../FilterFormItemModel';
|
||||
|
||||
describe('FilterFormItemModel getFilterValue', () => {
|
||||
@@ -174,4 +176,74 @@ describe('FilterFormItemModel getFilterValue', () => {
|
||||
const value = FilterFormItemModel.prototype.getFilterValue.call(model as any);
|
||||
expect(value).toBe(25);
|
||||
});
|
||||
|
||||
it('uses the tree Cascader leaf target key with the equality operator', () => {
|
||||
const engine = new FlowEngine();
|
||||
engine.registerModels({ CascadeSelectFieldModel });
|
||||
|
||||
const ds = engine.dataSourceManager.getDataSource('main');
|
||||
ds?.addCollection({
|
||||
name: 'organizations',
|
||||
template: 'tree',
|
||||
filterTargetKey: 'code',
|
||||
fields: [
|
||||
{ name: 'code', type: 'string', interface: 'input', filterable: { operators: [] } },
|
||||
{ name: 'name', type: 'string', interface: 'input', filterable: { operators: [] } },
|
||||
],
|
||||
});
|
||||
ds?.addCollection({
|
||||
name: 'users',
|
||||
fields: [
|
||||
{
|
||||
name: 'organization',
|
||||
type: 'belongsTo',
|
||||
interface: 'm2o',
|
||||
target: 'organizations',
|
||||
targetKey: 'code',
|
||||
filterable: { operators: [] },
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const fieldModel = engine.createModel<CascadeSelectFieldModel>({
|
||||
uid: 'tree-cascader-filter-field',
|
||||
use: 'CascadeSelectFieldModel',
|
||||
stepParams: {
|
||||
fieldSettings: {
|
||||
init: {
|
||||
dataSourceKey: 'main',
|
||||
collectionName: 'users',
|
||||
fieldPath: 'organization',
|
||||
},
|
||||
},
|
||||
},
|
||||
props: {
|
||||
fieldNames: { label: 'name', value: 'code' },
|
||||
value: {
|
||||
code: 'leaf',
|
||||
name: 'Leaf organization',
|
||||
parent: { code: 'root', name: 'Root organization', parent: null },
|
||||
},
|
||||
},
|
||||
});
|
||||
const model = {
|
||||
mounted: true,
|
||||
props: { name: 'organization' },
|
||||
subModels: { field: fieldModel },
|
||||
context: {
|
||||
form: {
|
||||
getFieldValue: vi.fn(() => fieldModel.props.value),
|
||||
},
|
||||
},
|
||||
getDefaultValue: vi.fn(() => undefined),
|
||||
getStepParams: vi.fn(() => undefined),
|
||||
getCurrentOperatorMeta: vi.fn(() => null),
|
||||
normalizeAssociationFilterValue: FilterFormItemModel.prototype.normalizeAssociationFilterValue,
|
||||
};
|
||||
|
||||
const value = FilterFormItemModel.prototype.getFilterValue.call(model as unknown as FilterFormItemModel);
|
||||
|
||||
expect(fieldModel.operator).toBe('$eq');
|
||||
expect(value).toBe('leaf');
|
||||
});
|
||||
});
|
||||
|
||||
+33
-1
@@ -8,7 +8,13 @@
|
||||
*/
|
||||
|
||||
import { Cascader, Space, Button } from 'antd';
|
||||
import { CollectionField, EditableItemModel, tExpr, MultiRecordResource } from '@nocobase/flow-engine';
|
||||
import {
|
||||
CollectionField,
|
||||
EditableItemModel,
|
||||
FilterableItemModel,
|
||||
MultiRecordResource,
|
||||
tExpr,
|
||||
} from '@nocobase/flow-engine';
|
||||
import { DeleteOutlined } from '@ant-design/icons';
|
||||
import { css, cx } from '@emotion/css';
|
||||
import { debounce, castArray, omit, last, isEqual } from 'lodash';
|
||||
@@ -31,6 +37,23 @@ function normalizeLabelKeys(labelKeyOrKeys?: string | string[]): string[] {
|
||||
return Array.from(new Set(list.filter((item): item is string => !!item && typeof item === 'string')));
|
||||
}
|
||||
|
||||
function normalizeCascadeFieldKey(key: unknown): string | undefined {
|
||||
if (typeof key === 'string' && key) {
|
||||
return key;
|
||||
}
|
||||
if (Array.isArray(key) && key.length === 1 && typeof key[0] === 'string') {
|
||||
return key[0];
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getDefaultCascadeFieldNames(field: CollectionField) {
|
||||
const targetCollection = field?.targetCollection;
|
||||
const value = normalizeCascadeFieldKey(targetCollection?.filterTargetKey) || 'id';
|
||||
const label = targetCollection?.titleCollectionField?.name || value;
|
||||
return { label, value };
|
||||
}
|
||||
|
||||
function getRecordDisplayLabel(item: any, labelKeyOrKeys?: string | string[]): string | null {
|
||||
if (!isPlainRecord(item)) return null;
|
||||
const labelKeys = normalizeLabelKeys(labelKeyOrKeys);
|
||||
@@ -815,6 +838,15 @@ EditableItemModel.bindModelToInterface('CascadeSelectFieldModel', ['m2o', 'o2o',
|
||||
order: 60,
|
||||
});
|
||||
|
||||
FilterableItemModel.bindModelToInterface('CascadeSelectFieldModel', ['m2o', 'o2o', 'oho', 'obo'], {
|
||||
when: (ctx, field) => field.targetCollection?.template === 'tree',
|
||||
isDefault: true,
|
||||
order: 60,
|
||||
defaultProps: (ctx, field) => ({
|
||||
fieldNames: getDefaultCascadeFieldNames(field),
|
||||
}),
|
||||
});
|
||||
|
||||
EditableItemModel.bindModelToInterface('CascadeSelectListFieldModel', ['m2m', 'o2m', 'mbm'], {
|
||||
when: (ctx, field) => field.targetCollection?.template === 'tree',
|
||||
isDefault: true,
|
||||
|
||||
+58
@@ -325,4 +325,62 @@ describe('flowSurfaces field binding registry', () => {
|
||||
),
|
||||
).toEqual(['DisplayTextFieldModel', 'DisplaySubListFieldModel', 'DisplaySubTableFieldModel']);
|
||||
});
|
||||
|
||||
it('should use Cascader for tree to-one filter fields without changing other relation defaults', () => {
|
||||
const treeToOneField = {
|
||||
interface: 'm2o',
|
||||
targetCollection: {
|
||||
template: 'tree',
|
||||
},
|
||||
};
|
||||
const generalToOneField = {
|
||||
interface: 'm2o',
|
||||
targetCollection: {
|
||||
template: 'general',
|
||||
},
|
||||
};
|
||||
const treeToManyField = {
|
||||
interface: 'm2m',
|
||||
targetCollection: {
|
||||
template: 'tree',
|
||||
},
|
||||
};
|
||||
|
||||
expect(
|
||||
resolveSupportedFieldCapability({
|
||||
containerUse: 'FilterFormBlockModel',
|
||||
field: treeToOneField,
|
||||
}),
|
||||
).toMatchObject({
|
||||
wrapperUse: 'FilterFormItemModel',
|
||||
fieldUse: 'CascadeSelectFieldModel',
|
||||
inferredFieldUse: 'CascadeSelectFieldModel',
|
||||
});
|
||||
expect(
|
||||
resolveSupportedFieldCapability({
|
||||
containerUse: 'FilterFormBlockModel',
|
||||
field: treeToOneField,
|
||||
requestedFieldUse: 'CascadeSelectFieldModel',
|
||||
}).fieldUse,
|
||||
).toBe('CascadeSelectFieldModel');
|
||||
expect(
|
||||
getSupportedFieldComponentUseSet({
|
||||
containerUse: 'FilterFormBlockModel',
|
||||
field: treeToOneField,
|
||||
})?.has('CascadeSelectFieldModel'),
|
||||
).toBe(true);
|
||||
|
||||
expect(
|
||||
resolveSupportedFieldCapability({
|
||||
containerUse: 'FilterFormBlockModel',
|
||||
field: generalToOneField,
|
||||
}).fieldUse,
|
||||
).toBe('FilterFormRecordSelectFieldModel');
|
||||
expect(
|
||||
resolveSupportedFieldCapability({
|
||||
containerUse: 'FilterFormBlockModel',
|
||||
field: treeToManyField,
|
||||
}).fieldUse,
|
||||
).toBe('FilterFormRecordSelectFieldModel');
|
||||
});
|
||||
});
|
||||
|
||||
+37
-2
@@ -117,6 +117,10 @@ describe('flowSurfaces field default bindings', () => {
|
||||
use: 'FilterFormItemModel',
|
||||
fieldUse: 'NumberFieldModel',
|
||||
});
|
||||
expect(findCatalogField(filterCatalog, 'organization')).toMatchObject({
|
||||
use: 'FilterFormItemModel',
|
||||
fieldUse: 'CascadeSelectFieldModel',
|
||||
});
|
||||
});
|
||||
|
||||
it('should use corrected default field models for addField addFields and compose write paths', async () => {
|
||||
@@ -138,6 +142,10 @@ describe('flowSurfaces field default bindings', () => {
|
||||
dataSourceKey: 'main',
|
||||
collectionName,
|
||||
});
|
||||
const filterFormUid = await addBlock(rootAgent, page.tabSchemaUid, 'filterForm', {
|
||||
dataSourceKey: 'main',
|
||||
collectionName,
|
||||
});
|
||||
|
||||
const displayField = await addField(rootAgent, tableUid, 'status');
|
||||
expect((await getSurface(rootAgent, { uid: displayField.fieldUid })).tree.use).toBe('DisplayEnumFieldModel');
|
||||
@@ -145,6 +153,13 @@ describe('flowSurfaces field default bindings', () => {
|
||||
const radioField = await addField(rootAgent, formUid, 'stage');
|
||||
expect((await getSurface(rootAgent, { uid: radioField.fieldUid })).tree.use).toBe('RadioGroupFieldModel');
|
||||
|
||||
const treeAssociationFilterField = await addField(rootAgent, filterFormUid, 'organization', {
|
||||
defaultTargetUid: tableUid,
|
||||
});
|
||||
expect((await getSurface(rootAgent, { uid: treeAssociationFilterField.fieldUid })).tree.use).toBe(
|
||||
'CascadeSelectFieldModel',
|
||||
);
|
||||
|
||||
const addFieldsRes = getData(
|
||||
await rootAgent.resource('flowSurfaces').addFields({
|
||||
values: {
|
||||
@@ -217,6 +232,17 @@ function getData(response: any) {
|
||||
|
||||
async function createFieldDefaultBindingCollection(rootAgent: any, app: MockServer, suffix: string) {
|
||||
const collectionName = `field_default_bindings_${suffix}_${Date.now()}`;
|
||||
const treeCollectionName = `${collectionName}_organizations`;
|
||||
const treeApplyResponse = await rootAgent.resource('collections').apply({
|
||||
values: {
|
||||
name: treeCollectionName,
|
||||
template: 'tree',
|
||||
titleField: 'name',
|
||||
fields: [{ name: 'name', type: 'string', interface: 'input' }],
|
||||
},
|
||||
});
|
||||
expect(treeApplyResponse.status).toBe(200);
|
||||
|
||||
const applyResponse = await rootAgent.resource('collections').apply({
|
||||
values: {
|
||||
name: collectionName,
|
||||
@@ -266,13 +292,21 @@ async function createFieldDefaultBindingCollection(rootAgent: any, app: MockServ
|
||||
type: 'integer',
|
||||
interface: 'number',
|
||||
},
|
||||
{
|
||||
name: 'organization',
|
||||
type: 'belongsTo',
|
||||
interface: 'm2o',
|
||||
target: treeCollectionName,
|
||||
foreignKey: 'organizationId',
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
expect(applyResponse.status).toBe(200);
|
||||
|
||||
await waitForFixtureCollectionsReady(app.db as any, {
|
||||
[collectionName]: ['title', 'status', 'stage', 'tags', 'enabled', 'rank'],
|
||||
[collectionName]: ['title', 'status', 'stage', 'tags', 'enabled', 'rank', 'organizationId'],
|
||||
[treeCollectionName]: ['name', 'parentId'],
|
||||
});
|
||||
|
||||
return collectionName;
|
||||
@@ -304,7 +338,7 @@ async function addBlock(rootAgent: any, targetUid: string, type: string, resourc
|
||||
).uid;
|
||||
}
|
||||
|
||||
async function addField(rootAgent: any, targetUid: string, fieldPath: string) {
|
||||
async function addField(rootAgent: any, targetUid: string, fieldPath: string, extraValues: Record<string, any> = {}) {
|
||||
return getData(
|
||||
await rootAgent.resource('flowSurfaces').addField({
|
||||
values: {
|
||||
@@ -312,6 +346,7 @@ async function addField(rootAgent: any, targetUid: string, fieldPath: string) {
|
||||
uid: targetUid,
|
||||
},
|
||||
fieldPath,
|
||||
...extraValues,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
+8
@@ -116,6 +116,14 @@ function selectPreferredDefaultRule(rules: FlowSurfaceFieldBindingRuleRecord[])
|
||||
}
|
||||
|
||||
const FIELD_BINDING_RULE_DEFINITIONS = [
|
||||
{
|
||||
scope: 'filter',
|
||||
modelClassName: 'CascadeSelectFieldModel',
|
||||
interfaces: ['m2o', 'o2o', 'oho', 'obo'],
|
||||
isDefault: true,
|
||||
order: 60,
|
||||
when: ({ targetCollection }) => getCollectionTemplate(targetCollection) === 'tree',
|
||||
},
|
||||
{
|
||||
scope: 'display',
|
||||
modelClassName: 'DisplayPreviewFieldModel',
|
||||
|
||||
Reference in New Issue
Block a user