From effff269dc113728966a2c6affe1b7aab291a519 Mon Sep 17 00:00:00 2001 From: by <738326776@qq.com> Date: Tue, 9 Jan 2024 12:21:16 +0800 Subject: [PATCH] fix: filter form drop-down selection to add data range (#3321) * fix: filter form drop-down selection to add data range * refactor: use existing code directly * test: add tests --------- Co-authored-by: zhangboya3 Co-authored-by: Zeke Zhang <958414905@qq.com> --- .../form-item/FormItem.FilterFormSettings.tsx | 67 +++- .../antd/form-item/FormItem.Settings.tsx | 7 +- .../antd/form-item/SchemaSettingOptions.tsx | 1 - packages/core/test/src/e2e/templatesOfPage.ts | 323 ++++++++++++++++++ .../fields/belongsTo/schemaSettings.test.ts | 24 ++ .../fields/hasOne/schemaSettings.test.ts | 24 ++ .../fields/manyToMany/schemaSettings.test.ts | 24 ++ .../fields/manyToOne/schemaSettings.test.ts | 24 ++ .../fields/oneToMany/schemaSettings.test.ts | 24 ++ 9 files changed, 511 insertions(+), 7 deletions(-) diff --git a/packages/core/client/src/schema-component/antd/form-item/FormItem.FilterFormSettings.tsx b/packages/core/client/src/schema-component/antd/form-item/FormItem.FilterFormSettings.tsx index 612c9313a..83d4d86dd 100644 --- a/packages/core/client/src/schema-component/antd/form-item/FormItem.FilterFormSettings.tsx +++ b/packages/core/client/src/schema-component/antd/form-item/FormItem.FilterFormSettings.tsx @@ -1,8 +1,17 @@ -import { SchemaSettings } from '../../../application/schema-settings'; -import { useFieldSchema } from '@formily/react'; +import { useField, useFieldSchema } from '@formily/react'; import _ from 'lodash'; +import React from 'react'; import { useTranslation } from 'react-i18next'; +import { SchemaSettings } from '../../../application/schema-settings'; +import { useFormBlockContext } from '../../../block-provider'; import { useCollection, useCollectionManager } from '../../../collection-manager'; +import { useRecord } from '../../../record-provider'; +import { SchemaSettingsDataScope, VariableInput, getShouldChange } from '../../../schema-settings'; +import { useLocalVariables, useVariables } from '../../../variables'; +import { useDesignable } from '../../hooks'; +import { removeNullCondition } from '../filter'; +import { DynamicComponentProps } from '../filter/DynamicComponent'; +import { useIsFormReadPretty, useIsSelectFieldMode } from './FormItem.Settings'; import { EditComponent, EditDescription, @@ -32,6 +41,60 @@ export const filterFormItemSettings = new SchemaSettings({ name: 'validationRules', Component: EditValidationRules, }, + { + name: 'setDataScope', + Component: SchemaSettingsDataScope, + useVisible() { + const isSelectFieldMode = useIsSelectFieldMode(); + const isFormReadPretty = useIsFormReadPretty(); + return isSelectFieldMode && !isFormReadPretty; + }, + useComponentProps() { + const { getCollectionJoinField, getAllCollectionsInheritChain } = useCollectionManager(); + const { getField } = useCollection(); + const { form } = useFormBlockContext(); + const record = useRecord(); + const field = useField(); + const fieldSchema = useFieldSchema(); + const collectionField = + getField(fieldSchema['name']) || getCollectionJoinField(fieldSchema['x-collection-field']); + const variables = useVariables(); + const localVariables = useLocalVariables(); + const { dn } = useDesignable(); + return { + collectionName: collectionField?.target, + defaultFilter: fieldSchema?.['x-component-props']?.service?.params?.filter || {}, + form, + dynamicComponent: (props: DynamicComponentProps) => { + return ( + + ); + }, + onSubmit: ({ filter }) => { + filter = removeNullCondition(filter); + _.set(field.componentProps, 'service.params.filter', filter); + fieldSchema['x-component-props'] = field.componentProps; + dn.emit('patch', { + schema: { + ['x-uid']: fieldSchema['x-uid'], + 'x-component-props': field.componentProps, + }, + }); + }, + }; + }, + }, { name: 'fieldMode', Component: EditComponent, diff --git a/packages/core/client/src/schema-component/antd/form-item/FormItem.Settings.tsx b/packages/core/client/src/schema-component/antd/form-item/FormItem.Settings.tsx index 63c66a968..42cbb68b9 100644 --- a/packages/core/client/src/schema-component/antd/form-item/FormItem.Settings.tsx +++ b/packages/core/client/src/schema-component/antd/form-item/FormItem.Settings.tsx @@ -1,7 +1,6 @@ import { ArrayCollapse, FormLayout } from '@formily/antd-v5'; import { Field } from '@formily/core'; import { ISchema, useField, useFieldSchema } from '@formily/react'; -import { Select } from 'antd'; import _ from 'lodash'; import React from 'react'; import { useTranslation } from 'react-i18next'; @@ -11,8 +10,8 @@ import { Collection, useCollection, useCollectionManager } from '../../../collec import { useRecord } from '../../../record-provider'; import { generalSettingsItems } from '../../../schema-items/GeneralSettings'; import { - SchemaSettingsDateFormat, SchemaSettingsDataScope, + SchemaSettingsDateFormat, SchemaSettingsDefaultValue, SchemaSettingsSortingRule, isPatternDisabled, @@ -862,7 +861,7 @@ function isFileCollection(collection: Collection) { return collection?.template === 'file'; } -function useIsFormReadPretty() { +export function useIsFormReadPretty() { const { form } = useFormBlockContext(); return !!form?.readPretty; } @@ -901,7 +900,7 @@ function useFieldMode() { return fieldMode; } -function useIsSelectFieldMode() { +export function useIsSelectFieldMode() { const fieldMode = useFieldMode(); const isAssociationField = useIsAssociationField(); const isSelectFieldMode = isAssociationField && fieldMode === 'Select'; diff --git a/packages/core/client/src/schema-component/antd/form-item/SchemaSettingOptions.tsx b/packages/core/client/src/schema-component/antd/form-item/SchemaSettingOptions.tsx index 401c8d762..b274881a8 100644 --- a/packages/core/client/src/schema-component/antd/form-item/SchemaSettingOptions.tsx +++ b/packages/core/client/src/schema-component/antd/form-item/SchemaSettingOptions.tsx @@ -16,7 +16,6 @@ import { import { useCompile, useDesignable, useFieldModeOptions } from '../../hooks'; import { useOperatorList } from '../filter/useOperators'; import { isFileCollection } from './FormItem'; - export const findFilterOperators = (schema: Schema) => { while (schema) { if (schema['x-filter-operators']) { diff --git a/packages/core/test/src/e2e/templatesOfPage.ts b/packages/core/test/src/e2e/templatesOfPage.ts index 641839c9a..4c087cc90 100644 --- a/packages/core/test/src/e2e/templatesOfPage.ts +++ b/packages/core/test/src/e2e/templatesOfPage.ts @@ -11070,6 +11070,329 @@ export const oneTableBlockWithAddNewAndViewAndEditAndAssociationFields: PageConf }, }; +/** + * 页面中有一个 filter form 区块,包含所有关系字段类型的字段 + */ +export const oneFilterFormBlockWithAllAssociationFields: PageConfig = { + collections: generalWithAssociation, + pageSchema: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Page', + properties: { + wwjstoiggum: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid', + 'x-initializer': 'BlockInitializers', + properties: { + oogm3hoka7c: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Row', + properties: { + '5zbwfzh1742': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Col', + properties: { + pwm2ca6igf0: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-decorator': 'FilterFormBlockProvider', + 'x-decorator-props': { + resource: 'general', + collection: 'general', + }, + 'x-designer': 'FormV2.FilterDesigner', + 'x-component': 'CardItem', + 'x-filter-targets': [], + 'x-filter-operators': {}, + properties: { + j2u0whpedfr: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'FormV2', + 'x-component-props': { + useProps: '{{ useFormBlockProps }}', + }, + properties: { + grid: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid', + 'x-initializer': 'FilterFormItemInitializers', + properties: { + y5gw4zxp20e: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Row', + properties: { + yflpc1gga26: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Col', + properties: { + oneToOneBelongsTo: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'string', + required: false, + 'x-designer': 'FormItem.FilterFormDesigner', + 'x-component': 'CollectionField', + 'x-decorator': 'FormItem', + 'x-collection-field': 'general.oneToOneBelongsTo', + 'x-component-props': { + multiple: false, + fieldNames: { + label: 'id', + value: 'id', + }, + }, + 'x-uid': '36aeb1yw2yy', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '4hc93v9beuk', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'u7avxnfj90q', + 'x-async': false, + 'x-index': 1, + }, + t2podb2p9ts: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Row', + properties: { + udslfw0t5vy: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Col', + properties: { + oneToOneHasOne: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'string', + required: false, + 'x-designer': 'FormItem.FilterFormDesigner', + 'x-component': 'CollectionField', + 'x-decorator': 'FormItem', + 'x-collection-field': 'general.oneToOneHasOne', + 'x-component-props': { + multiple: false, + fieldNames: { + label: 'id', + value: 'id', + }, + }, + 'x-uid': '945t8dkn7ab', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'alfh40hld9g', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'p0lrhxcpc30', + 'x-async': false, + 'x-index': 2, + }, + zzfk0g3yfjw: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Row', + properties: { + f2dxs9mqnhu: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Col', + properties: { + oneToMany: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'string', + required: false, + 'x-designer': 'FormItem.FilterFormDesigner', + 'x-component': 'CollectionField', + 'x-decorator': 'FormItem', + 'x-collection-field': 'general.oneToMany', + 'x-component-props': { + multiple: true, + fieldNames: { + label: 'id', + value: 'id', + }, + }, + 'x-uid': '8j8w5rtdhux', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'zvua8m975ql', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'bo6emdzi0ug', + 'x-async': false, + 'x-index': 3, + }, + '0klgdlg66ay': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Row', + properties: { + '12wu3wvgdhp': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Col', + properties: { + manyToOne: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'string', + required: false, + 'x-designer': 'FormItem.FilterFormDesigner', + 'x-component': 'CollectionField', + 'x-decorator': 'FormItem', + 'x-collection-field': 'general.manyToOne', + 'x-component-props': { + multiple: false, + fieldNames: { + label: 'id', + value: 'id', + }, + }, + 'x-uid': 'wcsgutero19', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '0zebcqxbskn', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'bc7dwbg9thk', + 'x-async': false, + 'x-index': 4, + }, + b7cs1das1cq: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Row', + properties: { + fza3rz9m06z: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Col', + properties: { + manyToMany: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'string', + required: false, + 'x-designer': 'FormItem.FilterFormDesigner', + 'x-component': 'CollectionField', + 'x-decorator': 'FormItem', + 'x-collection-field': 'general.manyToMany', + 'x-component-props': { + multiple: true, + fieldNames: { + label: 'id', + value: 'id', + }, + }, + 'x-uid': 'a04jfxgru7s', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'z0hmplugqhq', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'kmdbr7xi8xt', + 'x-async': false, + 'x-index': 5, + }, + }, + 'x-uid': 'qiaicku011z', + 'x-async': false, + 'x-index': 1, + }, + actions: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-initializer': 'FilterFormActionInitializers', + 'x-component': 'ActionBar', + 'x-component-props': { + layout: 'one-column', + style: { + float: 'right', + }, + }, + 'x-uid': '1d1t3jlg0sq', + 'x-async': false, + 'x-index': 2, + }, + }, + 'x-uid': 'sesnb8danbq', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '652vjaqp29u', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'crpdy0e3icr', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'rzvgkigetmc', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '9gdo96vyjl8', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '19vrqfukj5j', + 'x-async': true, + 'x-index': 1, + }, +}; + /** * 1. 一个 Table 区块 * 2. 点击 Add new 有一个 Form 区块 diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/belongsTo/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/belongsTo/schemaSettings.test.ts index 189f9a72c..4441b392a 100644 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/belongsTo/schemaSettings.test.ts +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/belongsTo/schemaSettings.test.ts @@ -2,6 +2,7 @@ import { Page, expect, expectSettingsMenu, + oneFilterFormBlockWithAllAssociationFields, oneTableBlockWithAddNewAndViewAndEditAndAssociationFields, test, } from '@nocobase/test/e2e'; @@ -519,6 +520,29 @@ test.describe('form item & view form', () => { }); }); +test.describe('form item & filter form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneFilterFormBlockWithAllAssociationFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('block-item-CollectionField-general-filter-form-general.oneToOneBelongsTo-').hover(); + await page.getByRole('button', { name: 'designer-schema-settings-CollectionField' }).hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Edit description', + 'Set the data scope', + 'Field component', + 'Title field', + 'Delete', + ], + }); + }); +}); + test.describe('table column & table', () => { test('supported options', async ({ page, mockPage, mockRecord }) => { const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/hasOne/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/hasOne/schemaSettings.test.ts index d04b56845..3a5ecb875 100644 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/hasOne/schemaSettings.test.ts +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/hasOne/schemaSettings.test.ts @@ -2,6 +2,7 @@ import { Page, expect, expectSettingsMenu, + oneFilterFormBlockWithAllAssociationFields, oneTableBlockWithAddNewAndViewAndEditAndAssociationFields, test, } from '@nocobase/test/e2e'; @@ -518,6 +519,29 @@ test.describe('form item & view form', () => { }); }); +test.describe('form item & filter form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneFilterFormBlockWithAllAssociationFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('block-item-CollectionField-general-filter-form-general.oneToOneHasOne-').hover(); + await page.getByRole('button', { name: 'designer-schema-settings-CollectionField' }).hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Edit description', + 'Set the data scope', + 'Field component', + 'Title field', + 'Delete', + ], + }); + }); +}); + test.describe('table column & table', () => { test('supported options', async ({ page, mockPage, mockRecord }) => { const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/manyToMany/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/manyToMany/schemaSettings.test.ts index 29091e583..d4e66140c 100644 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/manyToMany/schemaSettings.test.ts +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/manyToMany/schemaSettings.test.ts @@ -2,6 +2,7 @@ import { Page, expect, expectSettingsMenu, + oneFilterFormBlockWithAllAssociationFields, oneTableBlockWithAddNewAndViewAndEditAndAssociationFields, test, } from '@nocobase/test/e2e'; @@ -744,6 +745,29 @@ test.describe('form item & view form', () => { }); }); +test.describe('form item & filter form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneFilterFormBlockWithAllAssociationFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('block-item-CollectionField-general-filter-form-general.manyToMany-manyToMany').hover(); + await page.getByRole('button', { name: 'designer-schema-settings-CollectionField' }).hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Edit description', + 'Set the data scope', + 'Field component', + 'Title field', + 'Delete', + ], + }); + }); +}); + test.describe('table column & table', () => { test('supported options', async ({ page, mockPage, mockRecord }) => { const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/manyToOne/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/manyToOne/schemaSettings.test.ts index 97f6e6f3b..e258cc909 100644 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/manyToOne/schemaSettings.test.ts +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/manyToOne/schemaSettings.test.ts @@ -2,6 +2,7 @@ import { Page, expect, expectSettingsMenu, + oneFilterFormBlockWithAllAssociationFields, oneTableBlockWithAddNewAndViewAndEditAndAssociationFields, test, } from '@nocobase/test/e2e'; @@ -551,6 +552,29 @@ test.describe('form item & view form', () => { }); }); +test.describe('form item & filter form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneFilterFormBlockWithAllAssociationFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('block-item-CollectionField-general-filter-form-general.manyToOne-manyToOne').hover(); + await page.getByRole('button', { name: 'designer-schema-settings-CollectionField' }).hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Edit description', + 'Set the data scope', + 'Field component', + 'Title field', + 'Delete', + ], + }); + }); +}); + test.describe('table column & table', () => { test('supported options', async ({ page, mockPage, mockRecord }) => { const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit(); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/oneToMany/schemaSettings.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/oneToMany/schemaSettings.test.ts index defbe49d4..b5f74d374 100644 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/oneToMany/schemaSettings.test.ts +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/client/__e2e__/fields/oneToMany/schemaSettings.test.ts @@ -2,6 +2,7 @@ import { Page, expect, expectSettingsMenu, + oneFilterFormBlockWithAllAssociationFields, oneTableBlockWithAddNewAndViewAndEditAndAssociationFields, test, } from '@nocobase/test/e2e'; @@ -563,6 +564,29 @@ test.describe('form item & view form', () => { }); }); +test.describe('form item & filter form', () => { + test('supported options', async ({ page, mockPage }) => { + const nocoPage = await mockPage(oneFilterFormBlockWithAllAssociationFields).waitForInit(); + await nocoPage.goto(); + + await expectSettingsMenu({ + page, + showMenu: async () => { + await page.getByLabel('block-item-CollectionField-general-filter-form-general.oneToMany-oneToMany').hover(); + await page.getByRole('button', { name: 'designer-schema-settings-CollectionField' }).hover(); + }, + supportedOptions: [ + 'Edit field title', + 'Edit description', + 'Set the data scope', + 'Field component', + 'Title field', + 'Delete', + ], + }); + }); +}); + test.describe('table column & table', () => { test('supported options', async ({ page, mockPage, mockRecord }) => { const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();