From ec67f5fbc1a9bff739021b050fc37edec41356bd Mon Sep 17 00:00:00 2001 From: Zeke Zhang <958414905@qq.com> Date: Sun, 28 Jan 2024 09:22:53 +0800 Subject: [PATCH] feat: support to add filter blocks for relationship blocks (#3436) * refactor: use props to make more extensible * feat: support to add filter blocks for relationship blocks * test: fix error * test: fix error --- .../dialog/__e2e__/schemaInitializer.test.ts | 4 +- .../__e2e__/schemaInitializer.test.ts | 2 +- .../buttons/RecordBlockInitializers.tsx | 44 +++++++++++++++++++ .../buttons/TableSelectorInitializers.tsx | 10 +++++ .../items/DataBlockInitializer.tsx | 10 ++++- .../items/FilterCollapseBlockInitializer.tsx | 5 +-- .../items/FilterFormBlockInitializer.tsx | 5 +-- 7 files changed, 70 insertions(+), 10 deletions(-) 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 7f218d884..3dc59dd0e 100644 --- a/packages/core/client/src/modules/dialog/__e2e__/schemaInitializer.test.ts +++ b/packages/core/client/src/modules/dialog/__e2e__/schemaInitializer.test.ts @@ -74,7 +74,7 @@ test.describe('where to open a popup and what can be added to it', () => { // add blocks await page.getByLabel('schema-initializer-Grid-RecordBlockInitializers-general').hover(); await page.getByRole('menuitem', { name: 'Details' }).click(); - await page.getByText('Form').click(); + await page.getByText('Form').first().click(); await page.getByRole('menuitem', { name: 'Markdown' }).click(); await expect(page.getByText('GeneralConfigure actionsConfigure fields')).toBeVisible(); @@ -163,7 +163,7 @@ test.describe('where to open a popup and what can be added to it', () => { // add blocks await page.getByLabel('schema-initializer-Grid-RecordBlockInitializers-general').hover(); await page.getByRole('menuitem', { name: 'Details' }).click(); - await page.getByText('Form').click(); + await page.getByText('Form').first().click(); await page.getByRole('menuitem', { name: 'Markdown' }).click(); await expect(page.getByText('GeneralConfigure actionsConfigure fields')).toBeVisible(); diff --git a/packages/core/client/src/modules/form-edit/__e2e__/schemaInitializer.test.ts b/packages/core/client/src/modules/form-edit/__e2e__/schemaInitializer.test.ts index 3c1920001..f81394c78 100644 --- a/packages/core/client/src/modules/form-edit/__e2e__/schemaInitializer.test.ts +++ b/packages/core/client/src/modules/form-edit/__e2e__/schemaInitializer.test.ts @@ -8,7 +8,7 @@ test.describe('where edit form block can be added', () => { await page.getByLabel('action-Action.Link-Edit-update-general-table-0').click(); await page.getByLabel('schema-initializer-Grid-RecordBlockInitializers-general').hover(); - await page.getByText('Form').click(); + await page.getByText('Form').first().click(); await page.mouse.move(300, 0); await expect(page.getByLabel('block-item-CardItem-general-form')).toBeVisible(); diff --git a/packages/core/client/src/schema-initializer/buttons/RecordBlockInitializers.tsx b/packages/core/client/src/schema-initializer/buttons/RecordBlockInitializers.tsx index bcb9973f8..a7b1637a4 100644 --- a/packages/core/client/src/schema-initializer/buttons/RecordBlockInitializers.tsx +++ b/packages/core/client/src/schema-initializer/buttons/RecordBlockInitializers.tsx @@ -1,4 +1,5 @@ import { Schema, useFieldSchema } from '@formily/react'; +import { useMemo } from 'react'; import { useCollection, useCollectionManager } from '../..'; import { SchemaInitializerItemType, useSchemaInitializer } from '../../application'; import { SchemaInitializer } from '../../application/schema-initializer/SchemaInitializer'; @@ -247,6 +248,49 @@ export const recordBlockInitializers = new SchemaInitializer({ title: '{{t("Current record blocks")}}', useChildren: useRecordBlocks, }, + { + name: 'filterBlocks', + title: '{{t("Filter blocks")}}', + type: 'itemGroup', + children: [ + { + name: 'filterForm', + title: '{{t("Form")}}', + Component: 'FilterFormBlockInitializer', + useComponentProps() { + const collection = useCollection(); + const toManyField = useMemo( + () => collection.fields.filter((field) => ['hasMany', 'belongsToMany'].includes(field.type)), + [collection.fields], + ); + + return { + filterItems(item) { + return toManyField.some((field) => field.target === item.name); + }, + }; + }, + }, + { + name: 'filterCollapse', + title: '{{t("Collapse")}}', + Component: 'FilterCollapseBlockInitializer', + useComponentProps() { + const collection = useCollection(); + const toManyField = useMemo( + () => collection.fields.filter((field) => ['hasMany', 'belongsToMany'].includes(field.type)), + [collection.fields], + ); + + return { + filterItems(item) { + return toManyField.some((field) => field.target === item.name); + }, + }; + }, + }, + ], + }, { type: 'itemGroup', name: 'relationshipBlocks', diff --git a/packages/core/client/src/schema-initializer/buttons/TableSelectorInitializers.tsx b/packages/core/client/src/schema-initializer/buttons/TableSelectorInitializers.tsx index 616c20b17..b08f1b741 100644 --- a/packages/core/client/src/schema-initializer/buttons/TableSelectorInitializers.tsx +++ b/packages/core/client/src/schema-initializer/buttons/TableSelectorInitializers.tsx @@ -31,12 +31,22 @@ export const tableSelectorInitializers = new SchemaInitializer({ name: 'filterFormBlockInTableSelector', title: '{{t("Form")}}', Component: 'FilterFormBlockInitializer', + componentProps: { + filterItems() { + return false; + }, + }, collectionName: name, }, { name: 'filterCollapseBlockInTableSelector', title: '{{t("Collapse")}}', Component: 'FilterCollapseBlockInitializer', + componentProps: { + filterItems() { + return false; + }, + }, collectionName: name, }, ]; diff --git a/packages/core/client/src/schema-initializer/items/DataBlockInitializer.tsx b/packages/core/client/src/schema-initializer/items/DataBlockInitializer.tsx index e07651c40..ce98e755c 100644 --- a/packages/core/client/src/schema-initializer/items/DataBlockInitializer.tsx +++ b/packages/core/client/src/schema-initializer/items/DataBlockInitializer.tsx @@ -226,6 +226,7 @@ export interface DataBlockInitializerProps { name: string; title: string; items?: any[]; + filterItems?: (item: any, index: number, items: any[]) => boolean; componentType: string; } @@ -240,6 +241,7 @@ export const DataBlockInitializer = (props: DataBlockInitializerProps) => { name, title, items, + filterItems, } = props; const { insert } = useSchemaInitializer(); const compile = useCompile(); @@ -260,7 +262,13 @@ export const DataBlockInitializer = (props: DataBlockInitializerProps) => { [createBlockSchema, getTemplateSchemaByMode, insert, isCusomeizeCreate, onCreateBlockSchema, templateWrap], ); const defaultItems = useCollectionDataSourceItemsV2(componentType); - const menuChildren = useMemo(() => items || defaultItems, [items, defaultItems]); + const menuChildren = useMemo(() => { + const result = items || defaultItems; + if (filterItems) { + return result.filter(filterItems); + } + return result; + }, [items, defaultItems]); const childItems = useSchemaInitializerMenuItems(menuChildren, name, onClick); const [isOpenSubMenu, setIsOpenSubMenu] = useState(false); const searchedChildren = useMenuSearch(childItems, isOpenSubMenu); diff --git a/packages/core/client/src/schema-initializer/items/FilterCollapseBlockInitializer.tsx b/packages/core/client/src/schema-initializer/items/FilterCollapseBlockInitializer.tsx index 8a89581f7..1d6af4924 100644 --- a/packages/core/client/src/schema-initializer/items/FilterCollapseBlockInitializer.tsx +++ b/packages/core/client/src/schema-initializer/items/FilterCollapseBlockInitializer.tsx @@ -5,10 +5,9 @@ import { useSchemaInitializer, useSchemaInitializerItem } from '../../applicatio import { createCollapseBlockSchema } from '../utils'; import { DataBlockInitializer } from './DataBlockInitializer'; -export const FilterCollapseBlockInitializer = () => { +export const FilterCollapseBlockInitializer = ({ filterItems }) => { const itemConfig = useSchemaInitializerItem(); const { insert } = useSchemaInitializer(); - const items = itemConfig?.name === 'filterCollapseBlockInTableSelector' ? [] : undefined; return ( { }); insert(schema); }} - items={items} + filterItems={filterItems} /> ); }; diff --git a/packages/core/client/src/schema-initializer/items/FilterFormBlockInitializer.tsx b/packages/core/client/src/schema-initializer/items/FilterFormBlockInitializer.tsx index 4de4e8f26..0edcd1a27 100644 --- a/packages/core/client/src/schema-initializer/items/FilterFormBlockInitializer.tsx +++ b/packages/core/client/src/schema-initializer/items/FilterFormBlockInitializer.tsx @@ -4,9 +4,8 @@ import { useSchemaInitializerItem } from '../../application'; import { createFilterFormBlockSchema } from '../utils'; import { FilterBlockInitializer } from './FilterBlockInitializer'; -export const FilterFormBlockInitializer = (props) => { +export const FilterFormBlockInitializer = ({ filterItems }) => { const itemConfig = useSchemaInitializerItem(); - const items = itemConfig?.name === 'filterFormBlockInTableSelector' ? [] : undefined; return ( { return s; }} createBlockSchema={createFilterFormBlockSchema} - items={items} + filterItems={filterItems} /> ); };