fix(client-v2): hide relation operator setting (#10025)

This commit is contained in:
Zeke Zhang
2026-07-08 16:34:13 +08:00
committed by GitHub
parent 7a9b951e3e
commit 75a3fb4d44
2 changed files with 63 additions and 12 deletions
@@ -62,9 +62,25 @@ function isRecord(value: unknown): value is Record<string, unknown> {
return !!value && typeof value === 'object' && !Array.isArray(value);
}
interface CollectionFieldWithAssociationMarker {
isAssociationField?: () => boolean;
target?: unknown;
}
function hasAssociationMarker(value: unknown): value is CollectionFieldWithAssociationMarker {
return isRecord(value) && (typeof value.isAssociationField === 'function' || 'target' in value);
}
const isAssociationCollectionField = (collectionField: unknown) => {
if (!hasAssociationMarker(collectionField)) {
return false;
}
return collectionField.isAssociationField ? collectionField.isAssociationField() : Boolean(collectionField.target);
};
const normalizeAssociationDefaultFilterValue = (value: any, fieldModel: any) => {
const collectionField = fieldModel?.context?.collectionField;
if (!collectionField?.isAssociationField?.()) {
if (!isAssociationCollectionField(collectionField)) {
return value;
}
@@ -171,8 +187,7 @@ const buildFilterFormFieldItem = ({
if (!binding) {
return;
}
const isAssociation =
typeof field?.isAssociationField === 'function' ? field.isAssociationField() : Boolean(field?.target);
const isAssociation = isAssociationCollectionField(field);
const fieldModel =
isAssociation && ctxWithFlags.engine?.getModelClass?.('FilterFormRecordSelectFieldModel')
? 'FilterFormRecordSelectFieldModel'
@@ -507,10 +522,7 @@ export class FilterFormItemModel extends FilterableItemModel<{
const formValue = this.context.form?.getFieldValue(this.props.name);
const modelValue = fieldModel.getFilterValue ? fieldModel.getFilterValue() : formValue;
const collectionField = (fieldModel as any)?.context?.collectionField;
const isAssociationField =
typeof collectionField?.isAssociationField === 'function'
? collectionField.isAssociationField()
: !!collectionField?.target;
const isAssociationField = isAssociationCollectionField(collectionField);
const shouldUseFormValue =
isAssociationField &&
!this.mounted &&
@@ -547,11 +559,7 @@ export class FilterFormItemModel extends FilterableItemModel<{
return value;
}
const collectionField = (fieldModel as any)?.context?.collectionField;
const isAssociation =
typeof collectionField?.isAssociationField === 'function'
? collectionField.isAssociationField()
: !!collectionField?.target;
if (!isAssociation) {
if (!isAssociationCollectionField(collectionField)) {
return value;
}
const normalizedFieldNames = normalizeAssociationFieldNames(
@@ -798,6 +806,13 @@ FilterFormItemModel.registerFlow({
},
defaultOperator: {
use: 'defaultOperator',
hideInSettings(ctx) {
const collectionField =
ctx.collectionField ||
ctx.model?.context?.collectionField ||
ctx.model?.subModels?.field?.context?.collectionField;
return isAssociationCollectionField(collectionField);
},
},
operatorComponentProps: {
use: 'operatorComponentProps',
@@ -33,6 +33,42 @@ class DummyCollectionBlockModel extends CollectionBlockModel {
}
describe('FilterFormItemModel defineChildren association fields', () => {
it('hides default operator setting for association filter fields', () => {
const engine = new FlowEngine();
engine.registerModels({
FilterFormItemModel,
});
const filterItem = engine.createModel<FilterFormItemModel>({
uid: 'association-filter-item-settings',
use: 'FilterFormItemModel',
});
const defaultOperatorStep = filterItem.getFlow('filterFormItemSettings')?.steps?.defaultOperator as {
hideInSettings?: (ctx: {
collectionField?: unknown;
model?: {
subModels?: {
field?: {
context?: {
collectionField?: unknown;
};
};
};
};
}) => boolean;
};
expect(defaultOperatorStep?.hideInSettings?.({ collectionField: { isAssociationField: () => true } })).toBe(true);
expect(
defaultOperatorStep?.hideInSettings?.({
model: { subModels: { field: { context: { collectionField: { target: 'departments' } } } } },
}),
).toBe(true);
expect(defaultOperatorStep?.hideInSettings?.({ collectionField: { interface: 'input', type: 'string' } })).toBe(
false,
);
});
it('groups association target fields and supports recursive paths', async () => {
const engine = new FlowEngine();
engine.registerModels({