From d75db227770079bab907b5b5880e473cbb26245a Mon Sep 17 00:00:00 2001 From: Zeke Zhang <958414905@qq.com> Date: Sun, 7 Apr 2024 17:21:26 +0800 Subject: [PATCH] fix(connect-data-blocks): should immediately show in the drop-down menu (#3953) * test: add e2e tests * fix: should immediately show in the drop-down menu * fix: should not lose the filtering function when dragging and connecting --- .../src/filter-provider/FilterProvider.tsx | 16 +- .../table/__e2e__/schemaSettings.test.ts | 87 +++++++- .../table/__e2e__/templatesOfBug.ts | 190 ++++++++++++++++++ .../src/schema-settings/SchemaSettings.tsx | 2 + 4 files changed, 281 insertions(+), 14 deletions(-) diff --git a/packages/core/client/src/filter-provider/FilterProvider.tsx b/packages/core/client/src/filter-provider/FilterProvider.tsx index 730a30efb1..05c0d1904a 100644 --- a/packages/core/client/src/filter-provider/FilterProvider.tsx +++ b/packages/core/client/src/filter-provider/FilterProvider.tsx @@ -91,7 +91,7 @@ export const DataBlockCollector = ({ params?: { filter: FilterParam }; }) => { const collection = useCollection_deprecated(); - const { recordDataBlocks, removeDataBlock } = useFilterBlock(); + const { recordDataBlocks } = useFilterBlock(); const { service } = useBlockRequestContext(); const field = useField(); const fieldSchema = useFieldSchema(); @@ -153,12 +153,6 @@ export const DataBlockCollector = ({ if (shouldApplyFilter) addBlockToDataBlocks(); }, [addBlockToDataBlocks, shouldApplyFilter]); - useEffect(() => { - return () => { - removeDataBlock(fieldSchema['x-uid']); - }; - }, []); - return
{children}
; }; @@ -185,18 +179,14 @@ export const useFilterBlock = () => { if (existingBlock) { // 这里的值有可能会变化,所以需要更新 - existingBlock.service = block.service; - existingBlock.defaultFilter = block.defaultFilter; - existingBlock.dataLoadingMode = block.dataLoadingMode; + Object.assign(existingBlock, block); return; } // 由于 setDataBlocks 是异步操作,所以上面的 existingBlock 在判断时有可能用的是旧的 dataBlocks,所以下面还需要根据 uid 进行去重操作 setDataBlocks((prev) => uniqBy([...prev, block], 'uid')); }; const removeDataBlock = (uid: string) => { - const blocks = dataBlocks.filter((item) => item.uid !== uid); - if (blocks.length === dataBlocks.length) return; - + if (dataBlocks.every((item) => item.uid !== uid)) return; setDataBlocks((prev) => prev.filter((item) => item.uid !== uid)); }; diff --git a/packages/core/client/src/modules/blocks/data-blocks/table/__e2e__/schemaSettings.test.ts b/packages/core/client/src/modules/blocks/data-blocks/table/__e2e__/schemaSettings.test.ts index 9780a378b3..1afffa2291 100644 --- a/packages/core/client/src/modules/blocks/data-blocks/table/__e2e__/schemaSettings.test.ts +++ b/packages/core/client/src/modules/blocks/data-blocks/table/__e2e__/schemaSettings.test.ts @@ -10,7 +10,7 @@ import { twoTableWithAssociationFields, twoTableWithSameCollection, } from '@nocobase/test/e2e'; -import { T3843 } from './templatesOfBug'; +import { T3843, oneTableWithRoles } from './templatesOfBug'; test.describe('table block schema settings', () => { test('supported options', async ({ page, mockPage }) => { @@ -287,6 +287,91 @@ test.describe('table block schema settings', () => { }); test('connecting two blocks connected by a foreign key', async ({ page, mockPage, mockRecords }) => {}); + + test('should immediately show in the drop-down menu of Connect data blocks when adding a block for the first time', async ({ + page, + mockPage, + }) => { + await mockPage(oneTableWithRoles).goto(); + + // 1. 创建一个详情区块 + await page.getByLabel('schema-initializer-Grid-page:').hover(); + await page.getByRole('menuitem', { name: 'table Details right' }).hover(); + await page.getByRole('menuitem', { name: 'Roles' }).click(); + await page.mouse.move(300, 0); + await page.getByLabel('schema-initializer-Grid-details:configureFields-roles').hover(); + await page.getByRole('menuitem', { name: 'Role name' }).click(); + await page.mouse.move(300, 0); + + // 2. 创建的详情区块应该立即出现在 Connect data blocks 的下拉菜单中 + await page.getByLabel('block-item-CardItem-roles-table').hover(); + await page.getByLabel('designer-schema-settings-CardItem-blockSettings:table-roles').hover(); + await page.getByRole('menuitem', { name: 'Connect data blocks right' }).hover(); + await page.getByRole('menuitem', { name: 'Roles #' }).click(); + + // 3. 点击 Table 行,筛选功能应该正常 + // 初次点击,变为选中状态 + await page.getByRole('button', { name: 'Admin' }).click(); + await expect(page.getByLabel('block-item-CollectionField-').getByText('Admin')).toBeVisible(); + // 再次点击,取消选中状态 + await page.getByRole('button', { name: 'Admin' }).click(); + await expect(page.getByLabel('block-item-CollectionField-').getByText('Admin')).toBeHidden(); + + // 4. 删除详情区块,Connect data blocks 的下拉菜单应该立即消失 + await page.getByLabel('block-item-CardItem-roles-details').hover(); + await page.getByLabel('designer-schema-settings-CardItem-blockSettings:detailsWithPagination-roles').hover(); + await page.getByRole('menuitem', { name: 'Delete' }).click(); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + + await page.getByLabel('block-item-CardItem-roles-').hover(); + await page.getByLabel('designer-schema-settings-CardItem-blockSettings:table-roles').hover(); + await page.getByRole('menuitem', { name: 'Connect data blocks right' }).hover(); + await expect(page.getByRole('menuitem', { name: 'No blocks to connect' })).toBeVisible(); + }); + + test('should not lose the filtering function when dragging and connecting', async ({ page, mockPage }) => { + await mockPage(oneTableWithRoles).goto(); + + // 1. 创建一个详情区块 + await page.getByLabel('schema-initializer-Grid-page:').hover(); + await page.getByRole('menuitem', { name: 'table Details right' }).hover(); + await page.getByRole('menuitem', { name: 'Roles' }).click(); + await page.mouse.move(300, 0); + await page.getByLabel('schema-initializer-Grid-details:configureFields-roles').hover(); + await page.getByRole('menuitem', { name: 'Role name' }).click(); + await page.mouse.move(300, 0); + + // 2. 拖动详情区块 + await page.getByLabel('block-item-CardItem-roles-details').hover(); + await page + .getByLabel('designer-drag-handler-CardItem-blockSettings:detailsWithPagination-roles') + .dragTo(page.getByLabel('block-item-CardItem-roles-table')); + + // 3. 创建的详情区块应该立即出现在 Connect data blocks 的下拉菜单中 + await page.getByLabel('block-item-CardItem-roles-table').hover(); + await page.getByLabel('designer-schema-settings-CardItem-blockSettings:table-roles').hover(); + await page.getByRole('menuitem', { name: 'Connect data blocks right' }).hover(); + await page.getByRole('menuitem', { name: 'Roles #' }).click(); + + // 4. 点击 Table 行,筛选功能应该正常 + // 初次点击,变为选中状态 + await page.getByRole('button', { name: 'Admin' }).click(); + await expect(page.getByLabel('block-item-CollectionField-').getByText('Admin')).toBeVisible(); + // 再次点击,取消选中状态 + await page.getByRole('button', { name: 'Admin' }).click(); + await expect(page.getByLabel('block-item-CollectionField-').getByText('Admin')).toBeHidden(); + + // 5. 删除详情区块,Connect data blocks 的下拉菜单应该立即消失 + await page.getByLabel('block-item-CardItem-roles-details').hover(); + await page.getByLabel('designer-schema-settings-CardItem-blockSettings:detailsWithPagination-roles').hover(); + await page.getByRole('menuitem', { name: 'Delete' }).click(); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + + await page.getByLabel('block-item-CardItem-roles-').hover(); + await page.getByLabel('designer-schema-settings-CardItem-blockSettings:table-roles').hover(); + await page.getByRole('menuitem', { name: 'Connect data blocks right' }).hover(); + await expect(page.getByRole('menuitem', { name: 'No blocks to connect' })).toBeVisible(); + }); }); }); diff --git a/packages/core/client/src/modules/blocks/data-blocks/table/__e2e__/templatesOfBug.ts b/packages/core/client/src/modules/blocks/data-blocks/table/__e2e__/templatesOfBug.ts index eaf53302ab..b72b822c61 100644 --- a/packages/core/client/src/modules/blocks/data-blocks/table/__e2e__/templatesOfBug.ts +++ b/packages/core/client/src/modules/blocks/data-blocks/table/__e2e__/templatesOfBug.ts @@ -1169,3 +1169,193 @@ export const T3843 = { 'x-async': true, }, }; +export const oneTableWithRoles: PageConfig = { + pageSchema: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Page', + 'x-app-version': '0.21.0-alpha.5', + properties: { + g31hdrdqs8h: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid', + 'x-initializer': 'page:addBlock', + 'x-app-version': '0.21.0-alpha.5', + properties: { + w3qd8et7ny1: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Row', + 'x-app-version': '0.21.0-alpha.5', + properties: { + jy1b9o63ko7: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Col', + 'x-app-version': '0.21.0-alpha.5', + properties: { + iwtxze1jmpm: { + 'x-uid': 'exvpbgr35zn', + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-decorator': 'TableBlockProvider', + 'x-acl-action': 'roles:list', + 'x-use-decorator-props': 'useTableBlockDecoratorProps', + 'x-decorator-props': { + collection: 'roles', + dataSource: 'main', + action: 'list', + params: { + pageSize: 20, + }, + rowKey: 'name', + showIndex: true, + dragSort: false, + }, + 'x-toolbar': 'BlockSchemaToolbar', + 'x-settings': 'blockSettings:table', + 'x-component': 'CardItem', + 'x-filter-targets': [ + { + uid: 'a7n5crnwx91', + }, + { + uid: 'z10rv1j5j7x', + field: 'roles.name', + }, + ], + 'x-app-version': '0.21.0-alpha.5', + properties: { + actions: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-initializer': 'table:configureActions', + 'x-component': 'ActionBar', + 'x-component-props': { + style: { + marginBottom: 'var(--nb-spacing)', + }, + }, + 'x-app-version': '0.21.0-alpha.5', + 'x-uid': 'bz6xai67sd4', + 'x-async': false, + 'x-index': 1, + }, + '3r100r39y9k': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'array', + 'x-initializer': 'table:configureColumns', + 'x-component': 'TableV2', + 'x-use-component-props': 'useTableBlockProps', + 'x-component-props': { + rowKey: 'id', + rowSelection: { + type: 'checkbox', + }, + }, + 'x-app-version': '0.21.0-alpha.5', + properties: { + actions: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{ t("Actions") }}', + 'x-action-column': 'actions', + 'x-decorator': 'TableV2.Column.ActionBar', + 'x-component': 'TableV2.Column', + 'x-designer': 'TableV2.ActionColumnDesigner', + 'x-initializer': 'table:configureItemActions', + 'x-app-version': '0.21.0-alpha.5', + properties: { + huffguvj9ju: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-decorator': 'DndContext', + 'x-component': 'Space', + 'x-component-props': { + split: '|', + }, + 'x-app-version': '0.21.0-alpha.5', + 'x-uid': 'kumec65v6eo', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '0behu2op8h2', + 'x-async': false, + 'x-index': 1, + }, + o3kdcl5v6ex: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-decorator': 'TableV2.Column.Decorator', + 'x-toolbar': 'TableColumnSchemaToolbar', + 'x-settings': 'fieldSettings:TableColumn', + 'x-component': 'TableV2.Column', + 'x-app-version': '0.21.0-alpha.5', + properties: { + title: { + _isJSONSchemaObject: true, + version: '2.0', + 'x-collection-field': 'roles.title', + 'x-component': 'CollectionField', + 'x-component-props': { + ellipsis: true, + }, + 'x-read-pretty': true, + 'x-decorator': null, + 'x-decorator-props': { + labelStyle: { + display: 'none', + }, + }, + 'x-app-version': '0.21.0-alpha.5', + 'x-uid': 'yga0n3a2puj', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'd452dent98m', + 'x-async': false, + 'x-index': 2, + }, + }, + 'x-uid': 'byorarf2lw2', + 'x-async': false, + 'x-index': 2, + }, + }, + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'ousy05pzp3u', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'znu51ytf7f5', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'gvzvz05oi9h', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'mk589w74bvs', + 'x-async': true, + 'x-index': 1, + }, +}; diff --git a/packages/core/client/src/schema-settings/SchemaSettings.tsx b/packages/core/client/src/schema-settings/SchemaSettings.tsx index 7f347d5519..54081cfe0c 100644 --- a/packages/core/client/src/schema-settings/SchemaSettings.tsx +++ b/packages/core/client/src/schema-settings/SchemaSettings.tsx @@ -553,6 +553,7 @@ export const SchemaSettingsRemove: FC = (props) => { const form = useForm(); const { modal } = App.useApp(); const { removeActiveFieldName } = useFormActiveFields() || {}; + const { removeDataBlock } = useFilterBlock(); return ( = (props) => { field.setInitialValue(null); field.reset(); } + removeDataBlock(fieldSchema['x-uid']); }, }); }}