From b752e1afe099218ea08b81173bbecc65946febb3 Mon Sep 17 00:00:00 2001 From: sealday Date: Wed, 3 Apr 2024 20:02:39 +0800 Subject: [PATCH] feat: optimize block add menu --- .../components/SchemaInitializerSubMenu.tsx | 3 +- .../schema-initializer/hooks/index.tsx | 48 +- packages/core/client/src/locale/en_US.json | 1 + packages/core/client/src/locale/es_ES.json | 1 + packages/core/client/src/locale/fr_FR.json | 1 + packages/core/client/src/locale/ja_JP.json | 1 + packages/core/client/src/locale/ko_KR.json | 1 + packages/core/client/src/locale/ru_RU.json | 1 + packages/core/client/src/locale/tr_TR.json | 1 + packages/core/client/src/locale/uk_UA.json | 1 + packages/core/client/src/locale/zh-CN.json | 1 + packages/core/client/src/locale/zh-TW.json | 1 + .../disassociate/__e2e__/disassociate.test.ts | 3 +- .../__e2e__/schemaInitializer.test.ts | 4 +- .../table/__e2e__/schemaInitializer.test.ts | 6 +- .../dialog/__e2e__/schemaInitializer.test.ts | 152 ++- .../modules/dialog/__e2e__/templatesOfBug.ts | 907 ++++++++++++++++++ .../buttons/RecordBlockInitializers.tsx | 14 +- .../items/DataBlockInitializer.tsx | 25 +- .../client/src/schema-initializer/utils.ts | 83 +- packages/core/test/src/e2e/defineConfig.ts | 1 - packages/core/test/src/e2e/e2eUtils.ts | 4 + .../client/__e2e__/schemaInitializer.test.ts | 3 +- .../plugin-calendar/src/client/index.tsx | 1 + 24 files changed, 1209 insertions(+), 55 deletions(-) diff --git a/packages/core/client/src/application/schema-initializer/components/SchemaInitializerSubMenu.tsx b/packages/core/client/src/application/schema-initializer/components/SchemaInitializerSubMenu.tsx index e2c0056ce..93711b355 100644 --- a/packages/core/client/src/application/schema-initializer/components/SchemaInitializerSubMenu.tsx +++ b/packages/core/client/src/application/schema-initializer/components/SchemaInitializerSubMenu.tsx @@ -55,7 +55,8 @@ export const SchemaInitializerMenu: FC = (props) => { } .ant-menu-root { margin: 0 -${token.margin}px; - .ant-menu-submenu-title { + .ant-menu-submenu-title, + .ant-menu-item-only-child { margin-inline: 0; margin-block: 0; width: 100%; diff --git a/packages/core/client/src/application/schema-initializer/hooks/index.tsx b/packages/core/client/src/application/schema-initializer/hooks/index.tsx index 13dc41c1f..da3cad0e7 100644 --- a/packages/core/client/src/application/schema-initializer/hooks/index.tsx +++ b/packages/core/client/src/application/schema-initializer/hooks/index.tsx @@ -44,11 +44,16 @@ export function useGetSchemaInitializerMenuItems(onClick?: (args: any) => void) if (!item.key) { item.key = `${compiledTitle}-${indexA}`; } - return { - key: item.key, - label: element, - associationField: item.associationField, - }; + return item.associationField + ? { + key: item.key, + label: element, + associationField: item.associationField, + } + : { + key: item.key, + label: element, + }; } if (item.type === 'itemGroup') { const label = typeof compiledTitle === 'string' ? compiledTitle : item.title; @@ -77,19 +82,28 @@ export function useGetSchemaInitializerMenuItems(onClick?: (args: any) => void) const label = element || compiledTitle || item.label; const key = item.key || `${parentKey}-${compiledTitle}-${indexA}`; - return { - key, - label, - associationField: item.associationField, - onClick: (info) => { - if (info.key !== key) return; - if (item.onClick) { - item.onClick({ ...info, item }); - } else { - onClick?.({ ...info, item }); - } - }, + const handleClick = (info) => { + info.domEvent.stopPropagation(); + if (info.key !== key) return; + if (item.onClick) { + item.onClick({ ...info, item }); + } else { + onClick?.({ ...info, item }); + } }; + + return item.associationField + ? { + key, + label, + associationField: item.associationField, + onClick: handleClick, + } + : { + key, + label, + onClick: handleClick, + }; }); }, [compile, onClick], diff --git a/packages/core/client/src/locale/en_US.json b/packages/core/client/src/locale/en_US.json index 87a439dd5..457124d02 100644 --- a/packages/core/client/src/locale/en_US.json +++ b/packages/core/client/src/locale/en_US.json @@ -627,6 +627,7 @@ "Current user": "Current user", "Current role": "Current role", "Current record": "Current record", + "Associated records": "Associated records", "Parent record": "Parent record", "Current time": "Current time", "System variables": "System variables", diff --git a/packages/core/client/src/locale/es_ES.json b/packages/core/client/src/locale/es_ES.json index e2e5dfcfe..8d1f2f161 100644 --- a/packages/core/client/src/locale/es_ES.json +++ b/packages/core/client/src/locale/es_ES.json @@ -615,6 +615,7 @@ "Current user": "Usuario actual", "Current role": "Rol actual", "Current record": "Registro actual", + "Associated records": "Registros asociados", "Parent record": "Registro padre", "Current time": "Hora actual", "System variables": "Variables del sistema", diff --git a/packages/core/client/src/locale/fr_FR.json b/packages/core/client/src/locale/fr_FR.json index 06025ca41..ba04b2fe3 100644 --- a/packages/core/client/src/locale/fr_FR.json +++ b/packages/core/client/src/locale/fr_FR.json @@ -612,6 +612,7 @@ "Current user": "Utilisateur actuel", "Current role": "Rôle actuel", "Current record": "Enregistrement actuel", + "Associated records": "Enregistrements associés", "Parent record": "Enregistrement parent", "Current time": "Heure actuelle", "System variables": "Variables système", diff --git a/packages/core/client/src/locale/ja_JP.json b/packages/core/client/src/locale/ja_JP.json index 4b3e4cefa..0af8a9e78 100644 --- a/packages/core/client/src/locale/ja_JP.json +++ b/packages/core/client/src/locale/ja_JP.json @@ -515,6 +515,7 @@ "Current user": "現在のユーザー", "Current role": "現在の役割", "Current record": "現在のレコード", + "Associated records": "関連付けられたレコード", "Popup close method": "ポップアップを閉じる方法", "Automatic close": "自動で閉じる", "Manually close": "手動で閉じる", diff --git a/packages/core/client/src/locale/ko_KR.json b/packages/core/client/src/locale/ko_KR.json index c0b8cbd38..ebe0a3db8 100644 --- a/packages/core/client/src/locale/ko_KR.json +++ b/packages/core/client/src/locale/ko_KR.json @@ -640,6 +640,7 @@ "Current user": "현재 사용자", "Current role": "현재 역할", "Current record": "현재 레코드", + "Associated records": "관련 레코드", "Parent record": "상위 레코드", "Current time": "현재 시간", "Now": "지금", diff --git a/packages/core/client/src/locale/ru_RU.json b/packages/core/client/src/locale/ru_RU.json index 99f45d8ad..ab3b29c42 100644 --- a/packages/core/client/src/locale/ru_RU.json +++ b/packages/core/client/src/locale/ru_RU.json @@ -451,6 +451,7 @@ "Current user": "Текущий пользователь", "Current role": "Текущая роль", "Current record": "Текущая запись", + "Associated records": "Связанные записи", "Parent record": "Родительская запись", "Popup close method": "Метод закрытия всплывающего окна", "Automatic close": "Автоматическое закрытие", diff --git a/packages/core/client/src/locale/tr_TR.json b/packages/core/client/src/locale/tr_TR.json index 0cccd69d4..e7330214b 100644 --- a/packages/core/client/src/locale/tr_TR.json +++ b/packages/core/client/src/locale/tr_TR.json @@ -450,6 +450,7 @@ "Current user": "Seçili kullanıcı", "Current role": "Seçili rol", "Current record": "Seçili kayıt", + "Associated records": "İlişkili kayıtlar", "Parent record": "Üst kayıt", "Popup close method": "Açılır pencere kapatma metodu", "Automatic close": "Otomatik kapat", diff --git a/packages/core/client/src/locale/uk_UA.json b/packages/core/client/src/locale/uk_UA.json index a530f6cfb..b2e111885 100644 --- a/packages/core/client/src/locale/uk_UA.json +++ b/packages/core/client/src/locale/uk_UA.json @@ -632,6 +632,7 @@ "Current user": "Поточний користувач", "Current role": "Поточна роль", "Current record": "Поточний запис", + "Associated records": "Пов'язані записи", "Parent record": "Батьківський запис", "Current time": "Поточний час", "System variables": "Системні змінні", diff --git a/packages/core/client/src/locale/zh-CN.json b/packages/core/client/src/locale/zh-CN.json index 51a222ac2..3fe43bfca 100644 --- a/packages/core/client/src/locale/zh-CN.json +++ b/packages/core/client/src/locale/zh-CN.json @@ -645,6 +645,7 @@ "Current user": "当前用户", "Current role": "当前角色", "Current record": "当前记录", + "Associated records": "关联记录", "Parent record": "上级记录", "Current time": "当前时间", "Now": "现在", diff --git a/packages/core/client/src/locale/zh-TW.json b/packages/core/client/src/locale/zh-TW.json index 510910d3e..f3e19c0ff 100644 --- a/packages/core/client/src/locale/zh-TW.json +++ b/packages/core/client/src/locale/zh-TW.json @@ -640,6 +640,7 @@ "Current user": "當前使用者", "Current role": "當前角色", "Current record": "當前記錄", + "Associated records": "關聯記錄", "Parent record": "上級記錄", "Current time": "當前時間", "Now": "現在", diff --git a/packages/core/client/src/modules/actions/disassociate/__e2e__/disassociate.test.ts b/packages/core/client/src/modules/actions/disassociate/__e2e__/disassociate.test.ts index 51eb5753c..582f0c92a 100644 --- a/packages/core/client/src/modules/actions/disassociate/__e2e__/disassociate.test.ts +++ b/packages/core/client/src/modules/actions/disassociate/__e2e__/disassociate.test.ts @@ -9,7 +9,8 @@ test('basic', async ({ page, mockPage, mockRecord }) => { await page.getByLabel('action-Action.Link-Edit record-update-collection1-table-0').click(); await page.getByLabel('schema-initializer-Grid-popup').hover(); await page.getByRole('menuitem', { name: 'table Table right' }).hover(); - await page.getByRole('menuitem', { name: 'manyToMany -> collection2' }).click(); + await page.getByRole('menuitem', { name: 'Associated records' }).hover(); + await page.getByRole('menuitem', { name: 'manyToMany' }).click(); // 2. Table 中显示 Role UID 字段 await page diff --git a/packages/core/client/src/modules/blocks/data-blocks/details-single/__e2e__/schemaInitializer.test.ts b/packages/core/client/src/modules/blocks/data-blocks/details-single/__e2e__/schemaInitializer.test.ts index 811248edc..27d294aaa 100644 --- a/packages/core/client/src/modules/blocks/data-blocks/details-single/__e2e__/schemaInitializer.test.ts +++ b/packages/core/client/src/modules/blocks/data-blocks/details-single/__e2e__/schemaInitializer.test.ts @@ -9,7 +9,7 @@ test.describe('where single data details block can be added', () => { await page.getByLabel('action-Action.Link-View-view-general-table-0').click(); await page.getByLabel('schema-initializer-Grid-popup:common:addBlock-general').hover(); await page.getByRole('menuitem', { name: 'Details' }).hover(); - await page.getByRole('menuitem', { name: 'General' }).click(); + await page.getByRole('menuitem', { name: 'Current record' }).click(); await page.mouse.move(300, 0); await expect(page.getByLabel('block-item-CardItem-general-details')).toBeVisible(); @@ -25,7 +25,7 @@ test.describe('configure actions', () => { await page.getByLabel('action-Action.Link-View-view-general-table-0').click(); await page.getByLabel('schema-initializer-Grid-popup:common:addBlock-general').hover(); await page.getByRole('menuitem', { name: 'Details' }).hover(); - await page.getByRole('menuitem', { name: 'General' }).click(); + await page.getByRole('menuitem', { name: 'Current record' }).click(); await page.mouse.move(300, 0); // create edit ------------------------------------------------------------------------------------ diff --git a/packages/core/client/src/modules/blocks/data-blocks/table/__e2e__/schemaInitializer.test.ts b/packages/core/client/src/modules/blocks/data-blocks/table/__e2e__/schemaInitializer.test.ts index 157dbdd01..fdb325f89 100644 --- a/packages/core/client/src/modules/blocks/data-blocks/table/__e2e__/schemaInitializer.test.ts +++ b/packages/core/client/src/modules/blocks/data-blocks/table/__e2e__/schemaInitializer.test.ts @@ -21,7 +21,8 @@ test.describe('where table block can be added', () => { // 添加当前表关系区块 await page.getByLabel('schema-initializer-Grid-popup').hover(); await page.getByRole('menuitem', { name: 'table Table right' }).hover(); - await page.getByRole('menuitem', { name: 'childAssociationField ->' }).click(); + await page.getByRole('menuitem', { name: 'Associated records' }).hover(); + await page.getByRole('menuitem', { name: 'childAssociationField' }).click(); await page .getByTestId('drawer-Action.Container-childCollection-View record') .getByLabel('schema-initializer-TableV2-') @@ -31,7 +32,8 @@ test.describe('where table block can be added', () => { // 添加父表关系区块 await page.getByLabel('schema-initializer-Grid-popup').hover(); await page.getByRole('menuitem', { name: 'table Table right' }).hover(); - await page.getByRole('menuitem', { name: 'parentAssociationField ->' }).click(); + await page.getByRole('menuitem', { name: 'Associated records' }).hover(); + await page.getByRole('menuitem', { name: 'parentAssociationField' }).click(); await page.getByLabel('schema-initializer-TableV2-table:configureColumns-parentTargetCollection').hover(); await page.getByRole('menuitem', { name: 'parentTargetText' }).click(); diff --git a/packages/core/client/src/modules/dialog/__e2e__/schemaInitializer.test.ts b/packages/core/client/src/modules/dialog/__e2e__/schemaInitializer.test.ts index 0d7879d7f..7cf686c5a 100644 --- a/packages/core/client/src/modules/dialog/__e2e__/schemaInitializer.test.ts +++ b/packages/core/client/src/modules/dialog/__e2e__/schemaInitializer.test.ts @@ -6,6 +6,7 @@ import { oneFormBlockWithRolesFieldBasedUsers, test, } from '@nocobase/test/e2e'; +import { tableWithRoles, tableWithUsers, tableWithInherit, tableWithInheritWithoutAssociation } from './templatesOfBug'; test.describe('where to open a popup and what can be added to it', () => { test('add new', async ({ page, mockPage }) => { @@ -77,7 +78,7 @@ test.describe('where to open a popup and what can be added to it', () => { await expect(page.getByText('test8')).toBeVisible(); // add blocks - await addBlock(['table Details right', 'General']); + await addBlock(['table Details right', 'Current record']); await addBlock(['form Form (Edit)']); await addBlock(['Markdown']); @@ -105,16 +106,18 @@ test.describe('where to open a popup and what can be added to it', () => { await page.getByRole('button', { name: 'OK', exact: true }).click(); // add relationship blocks - await addBlock(['table Details right', 'Many to one']); + await addBlock(['table Details right', 'Associated records', 'Many to one']); await expect(page.getByLabel('block-item-CardItem-users-')).toBeVisible(); - await addBlock(['table Table right', 'One to many']); + await addBlock(['table Table right', 'Associated records', 'One to many']); await expect(page.getByLabel('block-item-CardItem-users-table')).toBeVisible(); async function addBlock(names: string[]) { await page.getByLabel('schema-initializer-Grid-popup').hover(); - for (const name of names) { - await page.getByRole('menuitem', { name }).click(); + for (let i = 0; i < names.length - 1; i++) { + const name = names[i]; + await page.getByRole('menuitem', { name }).hover(); } + await page.getByRole('menuitem', { name: names[names.length - 1] }).click(); await page.mouse.move(300, 0); } }); @@ -163,7 +166,7 @@ test.describe('where to open a popup and what can be added to it', () => { // add blocks await page.getByLabel('schema-initializer-Grid-popup:common:addBlock-general').hover(); await page.getByRole('menuitem', { name: 'Details' }).hover(); - await page.getByRole('menuitem', { name: 'General' }).click(); + await page.getByRole('menuitem', { name: 'Current record' }).click(); await page.getByLabel('schema-initializer-Grid-popup:common:addBlock-general').hover(); await page.getByRole('menuitem', { name: 'form Form (Edit)' }).first().click(); await page.getByLabel('schema-initializer-Grid-popup:common:addBlock-general').hover(); @@ -188,12 +191,14 @@ test.describe('where to open a popup and what can be added to it', () => { await page.getByLabel('schema-initializer-Grid-popup:common:addBlock-general').hover(); await page.getByRole('menuitem', { name: 'Details' }).hover(); + await page.getByRole('menuitem', { name: 'Associated records' }).hover(); await page.getByRole('menuitem', { name: 'Many to one' }).click(); await page.mouse.move(300, 0); await expect(page.getByLabel('block-item-CardItem-users-')).toBeVisible(); await page.getByLabel('schema-initializer-Grid-popup:common:addBlock-general').hover(); await page.getByRole('menuitem', { name: 'table Table right' }).hover(); + await page.getByRole('menuitem', { name: 'Associated records' }).hover(); await page.getByRole('menuitem', { name: 'One to many' }).click(); await page.mouse.move(300, 0); await expect(page.getByLabel('block-item-CardItem-users-table')).toBeVisible(); @@ -225,3 +230,138 @@ test.describe('where to open a popup and what can be added to it', () => { } }); }); + +test.describe('add blocks to the popup', () => { + test('no inheritance, no views, no association fields', async ({ page, mockPage }) => { + await mockPage(tableWithRoles).goto(); + + // 打开弹窗 + await page.getByLabel('action-Action.Link-View-view-roles-table-root').click(); + + // 直接点击 Details 选项创建详情区块 + await page.getByLabel('schema-initializer-Grid-popup').hover(); + await page.getByRole('menuitem', { name: 'table Details' }).click(); + await page.getByLabel('schema-initializer-Grid-details:configureFields-roles').hover(); + await page.getByRole('menuitem', { name: 'Role UID' }).click(); + await expect(page.getByLabel('block-item-CollectionField-Role').getByText('root')).toBeVisible(); + await page.mouse.move(300, 0); + + // 直接点击 Form(Edit) 选项创建表单区块 + await page.getByLabel('schema-initializer-Grid-popup').hover(); + await page.getByRole('menuitem', { name: 'form Form (Edit)' }).click(); + await page.getByLabel('schema-initializer-Grid-form:').hover(); + await page.getByRole('menuitem', { name: 'Role UID' }).click(); + await expect( + page.getByLabel('block-item-CollectionField-roles-form-roles.name-Role UID').getByRole('textbox'), + ).toHaveValue('root'); + }); + + test('no inheritance, no views, with association fields', async ({ page, mockPage }) => { + await mockPage(tableWithUsers).goto(); + + // 打开弹窗 + await page.getByLabel('action-Action.Link-View-view-').click(); + + // 通过点击 Current record 选项创建详情区块 + await page.getByLabel('schema-initializer-Grid-popup').hover(); + await page.getByRole('menuitem', { name: 'table Details right' }).hover(); + await page.getByRole('menuitem', { name: 'Current record' }).click(); + await page.getByLabel('schema-initializer-Grid-details:configureFields-users').hover(); + await page.getByRole('menuitem', { name: 'Nickname' }).click(); + await page.mouse.move(300, 0); + await expect(page.getByLabel('block-item-CollectionField-users').getByText('Super Admin')).toBeVisible(); + + // 通过 Association records 创建一个关系区块 + await page.getByLabel('schema-initializer-Grid-popup').hover(); + await page.getByRole('menuitem', { name: 'table Details right' }).hover(); + await page.getByRole('menuitem', { name: 'Associated records' }).hover(); + await page.getByRole('menuitem', { name: 'Roles' }).click(); + await page.getByLabel('schema-initializer-Grid-details:configureFields-roles').hover(); + await page.getByRole('menuitem', { name: 'Role UID' }).click(); + await page.mouse.move(300, 0); + await expect(page.getByLabel('block-item-CollectionField-roles').getByText('admin')).toBeVisible(); + }); + + test('with inheritance, with association fields', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(tableWithInherit).waitForInit(); + const fatherRecord = await mockRecord('father'); + await nocoPage.goto(); + + // 打开弹窗 + await page.getByLabel('action-Action.Link-View-view-father-table-0').click(); + + // 通过 Current record 创建详情区块 + await page.getByLabel('schema-initializer-Grid-popup').hover(); + await page.getByRole('menuitem', { name: 'table Details right' }).hover(); + await page.getByRole('menuitem', { name: 'Current record right' }).hover(); + await page.getByRole('menuitem', { name: 'father' }).click(); + await page.mouse.move(-300, 0); + await page.getByLabel('schema-initializer-Grid-details:configureFields-father').hover(); + await page.getByRole('menuitem', { name: 'singleLineText' }).click(); + await page.mouse.move(300, 0); + await expect( + page.getByLabel('block-item-CollectionField-father').getByText(fatherRecord.singleLineText), + ).toBeVisible(); + + // 通过 Association records 创建关系区块 + await page.getByLabel('schema-initializer-Grid-popup').hover(); + await page.getByRole('menuitem', { name: 'table Table right' }).hover(); + await page.getByRole('menuitem', { name: 'Associated records' }).hover(); + await page.getByRole('menuitem', { name: 'manyToMany' }).click(); + await page.mouse.move(-300, 0); + await page + .getByTestId('drawer-Action.Container-father-View record') + .getByLabel('schema-initializer-TableV2-') + .hover(); + await page.getByRole('menuitem', { name: 'singleLineText' }).click(); + await page.mouse.move(300, 0); + await expect( + page + .getByTestId('drawer-Action.Container-father-View record') + .getByLabel('block-item-CardItem-') + .getByRole('row') + .getByText(fatherRecord.manyToMany[0].singleLineText), + ).toBeVisible(); + }); + + test('with inheritance, no association fields', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(tableWithInheritWithoutAssociation).waitForInit(); + const fatherRecord = await mockRecord('father'); + await nocoPage.goto(); + + // 打开弹窗 + await page.getByLabel('action-Action.Link-View-view-father-table-0').click(); + + // 通过 Current record 创建详情区块 + await page.getByLabel('schema-initializer-Grid-popup').hover(); + await page.getByRole('menuitem', { name: 'table Details right' }).hover(); + await page.getByRole('menuitem', { name: 'Current record right' }).hover(); + await page.getByRole('menuitem', { name: 'father' }).click(); + await page.getByLabel('schema-initializer-Grid-details:configureFields-father').hover(); + await page.getByRole('menuitem', { name: 'singleLineText' }).click(); + await page.mouse.move(300, 0); + await expect( + page.getByLabel('block-item-CollectionField-father').getByText(fatherRecord.singleLineText), + ).toBeVisible(); + }); + + test('only support association fields', async ({ page, mockPage }) => { + await mockPage(tableWithUsers).goto(); + + // 打开弹窗 + await page.getByLabel('action-Action.Link-View-view-').click(); + + // 通过 Association records 创建一个关系区块 + await page.getByLabel('schema-initializer-Grid-popup').hover(); + await page.getByRole('menuitem', { name: 'table Table right' }).hover(); + await page.getByRole('menuitem', { name: 'Associated records' }).hover(); + await page.getByRole('menuitem', { name: 'Roles' }).click(); + await page + .getByTestId('drawer-Action.Container-users-View record') + .getByLabel('schema-initializer-TableV2-') + .hover(); + await page.getByRole('menuitem', { name: 'Role UID' }).click(); + await page.mouse.move(300, 0); + await expect(page.getByLabel('block-item-CardItem-roles-').getByRole('row').getByText('root')).toBeVisible(); + }); +}); diff --git a/packages/core/client/src/modules/dialog/__e2e__/templatesOfBug.ts b/packages/core/client/src/modules/dialog/__e2e__/templatesOfBug.ts index f2f1f583c..22c9718a0 100644 --- a/packages/core/client/src/modules/dialog/__e2e__/templatesOfBug.ts +++ b/packages/core/client/src/modules/dialog/__e2e__/templatesOfBug.ts @@ -1473,3 +1473,910 @@ export const T2838: PageConfig = { 'x-async': true, }, }; + +export const tableWithRoles: PageConfig = { + pageSchema: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Page', + properties: { + kuzmtxw0lbq: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid', + 'x-initializer': 'page:addBlock', + properties: { + '9snoybve3hf': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Row', + properties: { + uzodd1sblh8: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Col', + properties: { + t77ozlyo0r4: { + _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': [], + 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-uid': 'w07zcu825vu', + 'x-async': false, + 'x-index': 1, + }, + i8s4er3z53z: { + _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', + }, + }, + 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', + properties: { + cgxhx0pycze: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-decorator': 'DndContext', + 'x-component': 'Space', + 'x-component-props': { + split: '|', + }, + properties: { + l6zuv8kq3lz: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{ t("View") }}', + 'x-action': 'view', + 'x-toolbar': 'ActionSchemaToolbar', + 'x-settings': 'actionSettings:view', + 'x-component': 'Action.Link', + 'x-component-props': { + openMode: 'drawer', + }, + 'x-decorator': 'ACLActionProvider', + 'x-designer-props': { + linkageAction: true, + }, + properties: { + drawer: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{ t("View record") }}', + 'x-component': 'Action.Container', + 'x-component-props': { + className: 'nb-action-popup', + }, + properties: { + tabs: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Tabs', + 'x-component-props': {}, + 'x-initializer': 'TabPaneInitializers', + properties: { + tab1: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{t("Details")}}', + 'x-component': 'Tabs.TabPane', + 'x-designer': 'Tabs.Designer', + 'x-component-props': {}, + properties: { + grid: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid', + 'x-initializer': 'popup:common:addBlock', + 'x-uid': '2ty04bmiunh', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'ymqk4t82osd', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'tpv088lk09n', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'n1mmv9b43s7', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'qh62598r5nz', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'ovtpdelg5lo', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '0ck7uj73zdh', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '52a31apruw6', + 'x-async': false, + 'x-index': 2, + }, + }, + 'x-uid': '8n1731cywxw', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'ua6aed1x4ba', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'kplmcq59pey', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'v0qbl3nyzyo', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'nn6bi7v7ae0', + 'x-async': true, + 'x-index': 1, + }, +}; + +export const tableWithUsers = { + pageSchema: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Page', + properties: { + kuzmtxw0lbq: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid', + 'x-initializer': 'page:addBlock', + properties: { + au5iakeqo5e: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Row', + properties: { + '2p9r34ylza3': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Col', + properties: { + i0ywe80o2k0: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-decorator': 'TableBlockProvider', + 'x-acl-action': 'users:list', + 'x-use-decorator-props': 'useTableBlockDecoratorProps', + 'x-decorator-props': { + collection: 'users', + dataSource: 'main', + action: 'list', + params: { + pageSize: 20, + }, + rowKey: 'id', + showIndex: true, + dragSort: false, + }, + 'x-toolbar': 'BlockSchemaToolbar', + 'x-settings': 'blockSettings:table', + 'x-component': 'CardItem', + 'x-filter-targets': [], + 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-uid': 'e7ukdkylglc', + 'x-async': false, + 'x-index': 1, + }, + lbh0sin622q: { + _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', + }, + }, + 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', + properties: { + mp82chprh15: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-decorator': 'DndContext', + 'x-component': 'Space', + 'x-component-props': { + split: '|', + }, + properties: { + '68vzmm4j2v7': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{ t("View") }}', + 'x-action': 'view', + 'x-toolbar': 'ActionSchemaToolbar', + 'x-settings': 'actionSettings:view', + 'x-component': 'Action.Link', + 'x-component-props': { + openMode: 'drawer', + }, + 'x-decorator': 'ACLActionProvider', + 'x-designer-props': { + linkageAction: true, + }, + properties: { + drawer: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{ t("View record") }}', + 'x-component': 'Action.Container', + 'x-component-props': { + className: 'nb-action-popup', + }, + properties: { + tabs: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Tabs', + 'x-component-props': {}, + 'x-initializer': 'TabPaneInitializers', + properties: { + tab1: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{t("Details")}}', + 'x-component': 'Tabs.TabPane', + 'x-designer': 'Tabs.Designer', + 'x-component-props': {}, + properties: { + grid: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid', + 'x-initializer': 'popup:common:addBlock', + 'x-uid': 'v8mceafhtt9', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'xgev5isxh8c', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'zxhc26ocbwt', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '8y380jnrc91', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'fvyqc3l0nlz', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 's9cdwte7qb5', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'e1e3l9aoqlz', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '2eta2rrzfib', + 'x-async': false, + 'x-index': 2, + }, + }, + 'x-uid': 'vqxmw6sp0dp', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '1hdhsgoac99', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'delawmtj0ku', + 'x-async': false, + 'x-index': 2, + }, + }, + 'x-uid': 'v0qbl3nyzyo', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'nn6bi7v7ae0', + 'x-async': true, + 'x-index': 1, + }, +}; + +export const tableWithInherit = { + collections: [ + { + name: 'targetCollection', + fields: [ + { + type: 'string', + name: 'singleLineText', + interface: 'input', + }, + ], + }, + { + name: 'father', + fields: [ + { + type: 'string', + name: 'singleLineText', + interface: 'input', + }, + { + name: 'manyToMany', + interface: 'm2m', + target: 'targetCollection', + }, + ], + }, + { + name: 'children', + inherits: ['father'], + }, + ], + pageSchema: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Page', + properties: { + egrrnisc7pq: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid', + 'x-initializer': 'page:addBlock', + properties: { + bb1fa9y5wwh: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Row', + properties: { + m8lbibphksn: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Col', + properties: { + xj86s1jfwmk: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-decorator': 'TableBlockProvider', + 'x-acl-action': 'father:list', + 'x-use-decorator-props': 'useTableBlockDecoratorProps', + 'x-decorator-props': { + collection: 'father', + dataSource: 'main', + action: 'list', + params: { + pageSize: 20, + }, + rowKey: 'id', + showIndex: true, + dragSort: false, + }, + 'x-toolbar': 'BlockSchemaToolbar', + 'x-settings': 'blockSettings:table', + 'x-component': 'CardItem', + 'x-filter-targets': [], + 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-uid': '6j0p8tmwey7', + 'x-async': false, + 'x-index': 1, + }, + pm3vc0ire0v: { + _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', + }, + }, + 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', + properties: { + '6izaz7cwt1f': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-decorator': 'DndContext', + 'x-component': 'Space', + 'x-component-props': { + split: '|', + }, + properties: { + '9qgblzykl18': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{ t("View") }}', + 'x-action': 'view', + 'x-toolbar': 'ActionSchemaToolbar', + 'x-settings': 'actionSettings:view', + 'x-component': 'Action.Link', + 'x-component-props': { + openMode: 'drawer', + }, + 'x-decorator': 'ACLActionProvider', + 'x-designer-props': { + linkageAction: true, + }, + properties: { + drawer: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{ t("View record") }}', + 'x-component': 'Action.Container', + 'x-component-props': { + className: 'nb-action-popup', + }, + properties: { + tabs: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Tabs', + 'x-component-props': {}, + 'x-initializer': 'TabPaneInitializers', + properties: { + tab1: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{t("Details")}}', + 'x-component': 'Tabs.TabPane', + 'x-designer': 'Tabs.Designer', + 'x-component-props': {}, + properties: { + grid: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid', + 'x-initializer': 'popup:common:addBlock', + 'x-uid': '9h1njletm7j', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'y9y0jzcb2pp', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '4m51ixkzi6i', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'kt1n14v8q1u', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'tkod1lyrj9z', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'e84lmt2djp7', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '8pydvn47931', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'zyfhdizs6g3', + 'x-async': false, + 'x-index': 2, + }, + }, + 'x-uid': '4r6xuptmtw8', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '0aqn6al8phn', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'em7wvio4zan', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'd0zbm0ezhp5', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'qdffo69m238', + 'x-async': true, + 'x-index': 1, + }, +}; + +export const tableWithInheritWithoutAssociation = { + collections: [ + { + name: 'father', + fields: [ + { + type: 'string', + name: 'singleLineText', + interface: 'input', + }, + ], + }, + { + name: 'children', + inherits: ['father'], + }, + ], + pageSchema: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Page', + properties: { + egrrnisc7pq: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid', + 'x-initializer': 'page:addBlock', + properties: { + bb1fa9y5wwh: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Row', + properties: { + m8lbibphksn: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Col', + properties: { + xj86s1jfwmk: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-decorator': 'TableBlockProvider', + 'x-acl-action': 'father:list', + 'x-use-decorator-props': 'useTableBlockDecoratorProps', + 'x-decorator-props': { + collection: 'father', + dataSource: 'main', + action: 'list', + params: { + pageSize: 20, + }, + rowKey: 'id', + showIndex: true, + dragSort: false, + }, + 'x-toolbar': 'BlockSchemaToolbar', + 'x-settings': 'blockSettings:table', + 'x-component': 'CardItem', + 'x-filter-targets': [], + 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-uid': '6j0p8tmwey7', + 'x-async': false, + 'x-index': 1, + }, + pm3vc0ire0v: { + _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', + }, + }, + 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', + properties: { + '6izaz7cwt1f': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-decorator': 'DndContext', + 'x-component': 'Space', + 'x-component-props': { + split: '|', + }, + properties: { + '9qgblzykl18': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{ t("View") }}', + 'x-action': 'view', + 'x-toolbar': 'ActionSchemaToolbar', + 'x-settings': 'actionSettings:view', + 'x-component': 'Action.Link', + 'x-component-props': { + openMode: 'drawer', + }, + 'x-decorator': 'ACLActionProvider', + 'x-designer-props': { + linkageAction: true, + }, + properties: { + drawer: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{ t("View record") }}', + 'x-component': 'Action.Container', + 'x-component-props': { + className: 'nb-action-popup', + }, + properties: { + tabs: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Tabs', + 'x-component-props': {}, + 'x-initializer': 'TabPaneInitializers', + properties: { + tab1: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{t("Details")}}', + 'x-component': 'Tabs.TabPane', + 'x-designer': 'Tabs.Designer', + 'x-component-props': {}, + properties: { + grid: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid', + 'x-initializer': 'popup:common:addBlock', + 'x-uid': '9h1njletm7j', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'y9y0jzcb2pp', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '4m51ixkzi6i', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'kt1n14v8q1u', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'tkod1lyrj9z', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'e84lmt2djp7', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '8pydvn47931', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'zyfhdizs6g3', + 'x-async': false, + 'x-index': 2, + }, + }, + 'x-uid': '4r6xuptmtw8', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '0aqn6al8phn', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'em7wvio4zan', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'd0zbm0ezhp5', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'qdffo69m238', + 'x-async': true, + 'x-index': 1, + }, +}; diff --git a/packages/core/client/src/schema-initializer/buttons/RecordBlockInitializers.tsx b/packages/core/client/src/schema-initializer/buttons/RecordBlockInitializers.tsx index 441d0271e..9aad9733e 100644 --- a/packages/core/client/src/schema-initializer/buttons/RecordBlockInitializers.tsx +++ b/packages/core/client/src/schema-initializer/buttons/RecordBlockInitializers.tsx @@ -76,7 +76,7 @@ function useRecordBlocks() { return false; }, onlyCurrentDataSource: true, - // hideSearch: true, + hideSearch: true, componentType: 'ReadPrettyFormItem', createBlockSchema, templateWrap: useCallback( @@ -92,7 +92,6 @@ function useRecordBlocks() { [templateWrap, templateWrapOfAssociationDetailsWithoutPagination], ), showAssociationFields: true, - hideChildrenIfSingleCollection: true, }; }, }, @@ -115,12 +114,11 @@ function useRecordBlocks() { return false; }, onlyCurrentDataSource: true, - // hideSearch: true, + hideSearch: true, componentType: 'FormItem', createBlockSchema: createEditFormBlock, templateWrap: templateWrap, showAssociationFields: true, - hideChildrenIfSingleCollection: true, }; }, useVisible() { @@ -143,7 +141,7 @@ function useRecordBlocks() { return false; }, onlyCurrentDataSource: true, - // hideSearch: true, + hideSearch: true, componentType: 'FormItem', createBlockSchema: createAssociationFormBlock, templateWrap: templateWrap, @@ -179,7 +177,7 @@ function useRecordBlocks() { const { createAssociationTableBlock } = useCreateAssociationTableBlock(); return { - // hideSearch: true, + hideSearch: true, onlyCurrentDataSource: true, filterCollections({ associationField }) { if (associationField) { @@ -210,7 +208,7 @@ function useRecordBlocks() { const { createAssociationListBlock } = useCreateAssociationListBlock(); return { - // hideSearch: true, + hideSearch: true, onlyCurrentDataSource: true, filterCollections({ associationField }) { if (associationField) { @@ -241,7 +239,7 @@ function useRecordBlocks() { const { createAssociationGridCardBlock } = useCreateAssociationGridCardBlock(); return { - // hideSearch: true, + hideSearch: true, onlyCurrentDataSource: true, filterCollections({ associationField }) { if (associationField) { diff --git a/packages/core/client/src/schema-initializer/items/DataBlockInitializer.tsx b/packages/core/client/src/schema-initializer/items/DataBlockInitializer.tsx index 8bdf7e41f..adce62eda 100644 --- a/packages/core/client/src/schema-initializer/items/DataBlockInitializer.tsx +++ b/packages/core/client/src/schema-initializer/items/DataBlockInitializer.tsx @@ -277,6 +277,7 @@ export interface DataBlockInitializerProps { showAssociationFields?: boolean; /** 如果只有一项数据表时,不显示 children 列表 */ hideChildrenIfSingleCollection?: boolean; + items?: ReturnType[]; } export const DataBlockInitializer = (props: DataBlockInitializerProps) => { @@ -293,6 +294,7 @@ export const DataBlockInitializer = (props: DataBlockInitializerProps) => { showAssociationFields, hideChildrenIfSingleCollection, filterDataSource, + items: itemsFromProps, } = props; const { insert, setVisible } = useSchemaInitializer(); const compile = useCompile(); @@ -311,13 +313,17 @@ export const DataBlockInitializer = (props: DataBlockInitializerProps) => { }, [getTemplateSchemaByMode, insert, onCreateBlockSchema, setVisible, templateWrap], ); - const items = useCollectionDataSourceItems({ - componentName: componentType, - filter, - filterDataSource, - onlyCurrentDataSource, - showAssociationFields, - }); + const items = + itemsFromProps || + // eslint-disable-next-line react-hooks/rules-of-hooks + useCollectionDataSourceItems({ + componentName: componentType, + filter, + filterDataSource, + onlyCurrentDataSource, + showAssociationFields, + dataBlockInitializerProps: props, + }); const getMenuItems = useGetSchemaInitializerMenuItems(onClick); const childItems = useMemo(() => { return getMenuItems(items, name); @@ -326,8 +332,7 @@ export const DataBlockInitializer = (props: DataBlockInitializerProps) => { const searchedChildren = useMenuSearch({ data: childItems, openKeys: openMenuKeys, hideSearch }); const compiledMenuItems = useMemo(() => { let children = searchedChildren.filter((item) => item.key !== 'search' && item.key !== 'empty'); - const hasAssociationField = children.some((item) => item.associationField); - if (hideChildrenIfSingleCollection && !hasAssociationField && children.length === 1) { + if (hideChildrenIfSingleCollection && children.length === 1) { // 只有一项可选时,直接展开 children = children[0].children; } else { @@ -345,7 +350,7 @@ export const DataBlockInitializer = (props: DataBlockInitializerProps) => { children, }, ]; - }, [name, compile, title, icon, searchedChildren, onClick, props]); + }, [searchedChildren, hideChildrenIfSingleCollection, name, compile, title, icon, onClick, props]); if (childItems.length > 1 || (childItems.length === 1 && childItems[0].children?.length > 0)) { return ( diff --git a/packages/core/client/src/schema-initializer/utils.ts b/packages/core/client/src/schema-initializer/utils.ts index 1057e9845..84e231e30 100644 --- a/packages/core/client/src/schema-initializer/utils.ts +++ b/packages/core/client/src/schema-initializer/utils.ts @@ -5,6 +5,7 @@ import _ from 'lodash'; import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { + DataBlockInitializer, DataSource, SchemaInitializerItemType, useCollection, @@ -840,12 +841,14 @@ export const useCollectionDataSourceItems = ({ onlyCurrentDataSource = false, showAssociationFields, filterDataSource, + dataBlockInitializerProps, }: { componentName; filter?: (options: { collection?: Collection; associationField?: CollectionFieldOptions }) => boolean; onlyCurrentDataSource?: boolean; showAssociationFields?: boolean; filterDataSource?: (dataSource?: DataSource) => boolean; + dataBlockInitializerProps?: any; }) => { const { t } = useTranslation(); const dm = useDataSourceManager(); @@ -867,7 +870,8 @@ export const useCollectionDataSourceItems = ({ } const { getTemplatesByCollection } = useSchemaTemplateManager(); - const res = useMemo(() => { + + const noAssociationMenu = useMemo(() => { return allCollections.map(({ key, displayName, collections }) => ({ name: key, label: displayName, @@ -885,12 +889,80 @@ export const useCollectionDataSourceItems = ({ const inherits = _.toArray(collection?.inherits || []); if (item.name === collection?.name || inherits.some((inheritName) => inheritName === item.name)) return -1; }), - ...associationFields, ], })); - }, [allCollections, associationFields, componentName, getTemplatesByCollection, t]); + }, [allCollections, collection?.inherits, collection?.name, componentName, getTemplatesByCollection, t]); - return res; + // https://nocobase.height.app/T-3821 + // showAssociationFields 的值是固定不变的,所以在 if 语句里使用 hooks 是安全的 + if (showAssociationFields) { + // eslint-disable-next-line react-hooks/rules-of-hooks + return useMemo(() => { + const currentRecord = { + name: 'currentRecord', + collectionName: collection.name, + dataSource: collection.dataSource, + Component: DataBlockInitializer, + // 目的是使点击无效 + onClick() {}, + componentProps: { + ...dataBlockInitializerProps, + icon: null, + title: t('Current record'), + name: 'currentRecord', + hideSearch: false, + hideChildrenIfSingleCollection: true, + items: noAssociationMenu, + }, + }; + const associationRecords = { + name: 'associationRecords', + Component: DataBlockInitializer, + // 目的是使点击无效 + onClick() {}, + componentProps: { + ...dataBlockInitializerProps, + icon: null, + title: t('Associated records'), + name: 'associationRecords', + hideSearch: false, + items: [ + { + name: 'associationFields', + label: t('Association fields'), + type: 'subMenu', // 这里套一层 subMenu 是因为 DataBlockInitializer 组件需要这样的数据结构,其实这层 subMenu 最终是不会渲染出来的 + children: associationFields, + }, + ], + }, + }; + let children; + + if (noAssociationMenu[0].children.length && associationFields.length) { + children = [currentRecord, associationRecords]; + } else if (noAssociationMenu[0].children.length) { + // 当可选数据表只有一个时,实现只点击一次区块 menu 就能创建区块 + if (noAssociationMenu[0].children.length <= 1) { + noAssociationMenu[0].children = (noAssociationMenu[0].children[0]?.children as any) || []; + return noAssociationMenu; + } + children = [currentRecord]; + } else { + children = [associationRecords]; + } + + return [ + { + name: 'records', + label: t('Records'), + type: 'subMenu', + children, + }, + ]; + }, [associationFields, collection.dataSource, collection.name, dataBlockInitializerProps, noAssociationMenu, t]); + } + + return noAssociationMenu; }; export const createDetailsBlockSchema = (options: { @@ -1396,8 +1468,7 @@ function useAssociationFields({ .filter((field) => ['linkTo', 'subTable', 'o2m', 'm2m', 'obo', 'oho', 'o2o', 'm2o'].includes(field.interface)) .filter((field) => filterCollections({ associationField: field })) .map((field, index) => { - const targetCollection = cm.getCollection(field.target); - const title = `${compile(field.uiSchema.title || field.name)} -> ${compile(targetCollection.title)}`; + const title = compile(field.uiSchema.title || field.name); const templates = getTemplatesByCollection(dataSource, field.target).filter((template) => { // 针对弹窗中的详情区块 if (componentName === 'ReadPrettyFormItem') { diff --git a/packages/core/test/src/e2e/defineConfig.ts b/packages/core/test/src/e2e/defineConfig.ts index 441b78044..a8bf694e0 100644 --- a/packages/core/test/src/e2e/defineConfig.ts +++ b/packages/core/test/src/e2e/defineConfig.ts @@ -20,7 +20,6 @@ export const defineConfig = (config?: PlaywrightTestConfig) => { // Fail the build on CI if you accidentally left test.only in the source code. forbidOnly: !!process.env.CI, - // Retry on CI only. retries: 2, // Opt out of parallel tests on CI. diff --git a/packages/core/test/src/e2e/e2eUtils.ts b/packages/core/test/src/e2e/e2eUtils.ts index 5f21adeb1..36c281af0 100644 --- a/packages/core/test/src/e2e/e2eUtils.ts +++ b/packages/core/test/src/e2e/e2eUtils.ts @@ -53,6 +53,7 @@ export interface CollectionSetting { * @default false */ inherit?: boolean; + inherits?: string[]; category?: any[]; hidden?: boolean; description?: string; @@ -620,6 +621,9 @@ const deleteCollections = async (collectionNames: string[]) => { const result = await api.post(`/api/collections:destroy?${params}`, { headers, + params: { + cascade: true, + }, }); if (!result.ok()) { diff --git a/packages/plugins/@nocobase/plugin-calendar/src/client/__e2e__/schemaInitializer.test.ts b/packages/plugins/@nocobase/plugin-calendar/src/client/__e2e__/schemaInitializer.test.ts index 2a2792c66..8a6f3143f 100644 --- a/packages/plugins/@nocobase/plugin-calendar/src/client/__e2e__/schemaInitializer.test.ts +++ b/packages/plugins/@nocobase/plugin-calendar/src/client/__e2e__/schemaInitializer.test.ts @@ -24,7 +24,8 @@ test.describe('where can be added', () => { await page.getByLabel('action-Action.Link-View-view-').first().click(); await page.getByLabel('schema-initializer-Grid-popup').hover(); await page.getByRole('menuitem', { name: 'form Calendar right' }).hover(); - await page.getByRole('menuitem', { name: 'manyToMany -> calendar' }).click(); + await page.getByRole('menuitem', { name: 'Associated records' }).hover(); + await page.getByRole('menuitem', { name: 'manyToMany' }).click(); await page.getByLabel('block-item-Select-Title field').getByTestId('select-single').click(); await page.getByRole('option', { name: 'Repeats' }).click(); diff --git a/packages/plugins/@nocobase/plugin-calendar/src/client/index.tsx b/packages/plugins/@nocobase/plugin-calendar/src/client/index.tsx index 9d281eaa3..e45f6227b 100644 --- a/packages/plugins/@nocobase/plugin-calendar/src/client/index.tsx +++ b/packages/plugins/@nocobase/plugin-calendar/src/client/index.tsx @@ -51,6 +51,7 @@ export class PluginCalendarClient extends Plugin { }, createBlockSchema: createAssociationCalendarBlock, showAssociationFields: true, + hideSearch: true, }; }, });