From adfb78d9368e3846a0f31b462ba24a7ae9db58e0 Mon Sep 17 00:00:00 2001 From: sealday Date: Tue, 7 May 2024 01:19:24 +0800 Subject: [PATCH] feat: support other collection in popup (#916) close #838 Co-authored-by: sealday Reviewed-on: https://git.daoyoucloud.com/daoyoucloud/tachybase/pulls/916 --- .../src/modules/blocks/BlockSchemaToolbar.tsx | 47 +++++- .../details-multi/DetailsBlockInitializer.tsx | 45 ++++-- .../data-blocks/form/FormBlockInitializer.tsx | 76 ++++++---- .../grid-card/GridCardBlockInitializer.tsx | 34 +++-- .../createGridCardBlockSchema.test.ts | 2 +- ...hema.ts => createGridCardBlockUISchema.ts} | 2 +- .../data-blocks/list/ListBlockInitializer.tsx | 35 +++-- .../__tests__/createListBlockSchema.test.ts | 2 +- ...ckSchema.ts => createListBlockUISchema.ts} | 2 +- .../table/TableBlockInitializer.tsx | 32 ++-- .../buttons/RecordBlockInitializers.tsx | 103 ++++++------- .../items/DataBlockInitializer.tsx | 19 ++- ...ordAssociationGridCardBlockInitializer.tsx | 6 +- .../RecordAssociationListBlockInitializer.tsx | 6 +- .../client/src/schema-initializer/utils.ts | 71 +++++++-- .../plugin-calendar/src/client/index.tsx | 24 ++- .../items/CalendarBlockInitializer.tsx | 137 ++++++++++-------- 17 files changed, 412 insertions(+), 231 deletions(-) rename packages/core/client/src/modules/blocks/data-blocks/grid-card/{createGridCardBlockSchema.ts => createGridCardBlockUISchema.ts} (97%) rename packages/core/client/src/modules/blocks/data-blocks/list/{createListBlockSchema.ts => createListBlockUISchema.ts} (97%) diff --git a/packages/core/client/src/modules/blocks/BlockSchemaToolbar.tsx b/packages/core/client/src/modules/blocks/BlockSchemaToolbar.tsx index 2e1a1c97a..7a0dfcdc5 100644 --- a/packages/core/client/src/modules/blocks/BlockSchemaToolbar.tsx +++ b/packages/core/client/src/modules/blocks/BlockSchemaToolbar.tsx @@ -1,19 +1,58 @@ import React, { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; -import { useCollection_deprecated } from '../../collection-manager'; +import { useCollectionManager, useDataBlockProps } from '../../data-source'; +import { useCollection } from '../../data-source/collection/CollectionProvider'; +import { useCompile } from '../../schema-component'; import { SchemaToolbar } from '../../schema-settings/GeneralSchemaDesigner'; import { useSchemaTemplate } from '../../schema-templates'; export const BlockSchemaToolbar = (props) => { const { t } = useTranslation(); - const { name, title } = useCollection_deprecated(); + const cm = useCollectionManager(); + let { name: currentCollectionName, title: currentCollectionTitle } = useCollection(); const template = useSchemaTemplate(); + const { association } = useDataBlockProps() || {}; + const compile = useCompile(); + + if (association) { + const [collectionName] = association.split('.'); + const { name, title } = cm.getCollection(collectionName); + currentCollectionName = name; + currentCollectionTitle = title; + } + + const associationField = cm.getCollectionField(association); const templateName = ['FormItem', 'ReadPrettyFormItem'].includes(template?.componentName) ? `${template?.name} ${t('(Fields only)')}` : template?.name; const toolbarTitle = useMemo(() => { - return [title || name, templateName].filter(Boolean); - }, [name, templateName, title]); + return [ + getCollectionTitle({ + collectionTitle: currentCollectionTitle, + collectionName: currentCollectionName, + associationField, + compile, + }), + templateName, + ].filter(Boolean); + }, [compile, currentCollectionTitle, currentCollectionName, associationField, templateName]); return ; }; + +function getCollectionTitle(props: { + collectionTitle: string; + collectionName: string; + associationField: any; + compile: any; +}) { + const { collectionTitle, collectionName, associationField, compile } = props; + + if (associationField) { + return `${compile(collectionTitle || collectionName)} > ${compile( + associationField.uiSchema?.title || associationField.name, + )}`; + } + + return collectionTitle || collectionName; +} diff --git a/packages/core/client/src/modules/blocks/data-blocks/details-multi/DetailsBlockInitializer.tsx b/packages/core/client/src/modules/blocks/data-blocks/details-multi/DetailsBlockInitializer.tsx index 11abe4a9b..b275206e8 100644 --- a/packages/core/client/src/modules/blocks/data-blocks/details-multi/DetailsBlockInitializer.tsx +++ b/packages/core/client/src/modules/blocks/data-blocks/details-multi/DetailsBlockInitializer.tsx @@ -1,7 +1,7 @@ import { TableOutlined } from '@ant-design/icons'; -import React from 'react'; +import React, { useCallback } from 'react'; import { useSchemaInitializer, useSchemaInitializerItem } from '../../../../application'; -import { useCollectionManager_deprecated } from '../../../../collection-manager'; +import { useCollectionManager } from '../../../../data-source'; import { DataBlockInitializer } from '../../../../schema-initializer/items/DataBlockInitializer'; import { Collection, CollectionFieldOptions } from '../../../../data-source/collection/Collection'; import { createDetailsWithPaginationUISchema } from './createDetailsWithPaginationUISchema'; @@ -36,9 +36,8 @@ export const DetailsBlockInitializer = ({ showAssociationFields?: boolean; hideChildrenIfSingleCollection?: boolean; }) => { - const { insert } = useSchemaInitializer(); - const { getCollection } = useCollectionManager_deprecated(); const itemConfig = useSchemaInitializerItem(); + const { createDetailsBlock } = useCreateDetailsBlock(); return ( ); }; + +export const useCreateDetailsBlock = () => { + const { insert } = useSchemaInitializer(); + // const { getCollection } = useCollectionManager_deprecated(); + const cm = useCollectionManager(); + + const createDetailsBlock = useCallback( + ({ item }) => { + const collection = cm.getCollection(item.name); + const schema = createDetailsWithPaginationUISchema({ + collectionName: item.name, + dataSource: item.dataSource, + rowKey: collection.filterTargetKey || 'id', + hideActionInitializer: !( + (collection.template !== 'view' || collection?.writableView) && + collection.template !== 'sql' + ), + }); + insert(schema); + }, + [cm, insert], + ); + + return { createDetailsBlock }; +}; diff --git a/packages/core/client/src/modules/blocks/data-blocks/form/FormBlockInitializer.tsx b/packages/core/client/src/modules/blocks/data-blocks/form/FormBlockInitializer.tsx index e86edbbdd..f3f5caf86 100644 --- a/packages/core/client/src/modules/blocks/data-blocks/form/FormBlockInitializer.tsx +++ b/packages/core/client/src/modules/blocks/data-blocks/form/FormBlockInitializer.tsx @@ -11,9 +11,10 @@ export const FormBlockInitializer = ({ hideSearch, createBlockSchema, componentType = 'FormItem', - templateWrap, + templateWrap: customizeTemplateWrap, showAssociationFields, hideChildrenIfSingleCollection, + hideOtherRecordsInPopup, }: { filterCollections: (options: { collection?: Collection; associationField?: CollectionFieldOptions }) => boolean; onlyCurrentDataSource: boolean; @@ -33,25 +34,22 @@ export const FormBlockInitializer = ({ ) => any; showAssociationFields?: boolean; hideChildrenIfSingleCollection?: boolean; + /** + * 隐藏弹窗中的 Other records 选项 + */ + hideOtherRecordsInPopup?: boolean; }) => { - const { insert } = useSchemaInitializer(); const itemConfig = useSchemaInitializerItem(); - const { isCusomeizeCreate } = itemConfig; + const { createFormBlock, templateWrap } = useCreateFormBlock(); const onCreateFormBlockSchema = useCallback( - ({ item }) => { + (options) => { if (createBlockSchema) { - return createBlockSchema({ item }); + return createBlockSchema(options); } - insert( - createCreateFormBlockUISchema({ - collectionName: item.collectionName || item.name, - dataSource: item.dataSource, - isCusomeizeCreate, - }), - ); + createFormBlock(options); }, - [createBlockSchema, insert, isCusomeizeCreate], + [createBlockSchema, createFormBlock], ); return ( @@ -59,21 +57,12 @@ export const FormBlockInitializer = ({ {...itemConfig} icon={} componentType={componentType} - templateWrap={(templateSchema, { item }) => { - if (templateWrap) { - return templateWrap(templateSchema, { item }); + templateWrap={(templateSchema, options) => { + if (customizeTemplateWrap) { + return customizeTemplateWrap(templateSchema, options); } - const schema = createCreateFormBlockUISchema({ - isCusomeizeCreate, - dataSource: item.dataSource, - templateSchema: templateSchema, - collectionName: item.name, - }); - if (item.template && item.mode === 'reference') { - schema['x-template-key'] = item.template.key; - } - return schema; + return templateWrap(templateSchema, options); }} onCreateBlockSchema={onCreateFormBlockSchema} filter={filterCollections} @@ -81,6 +70,41 @@ export const FormBlockInitializer = ({ hideSearch={hideSearch} showAssociationFields={showAssociationFields} hideChildrenIfSingleCollection={hideChildrenIfSingleCollection} + hideOtherRecordsInPopup={hideOtherRecordsInPopup} /> ); }; + +export const useCreateFormBlock = () => { + const { insert } = useSchemaInitializer(); + const itemConfig = useSchemaInitializerItem(); + const { isCusomeizeCreate: isCustomizeCreate } = itemConfig; + + const createFormBlock = ({ item }) => { + insert( + createCreateFormBlockUISchema({ + collectionName: item.collectionName || item.name, + dataSource: item.dataSource, + isCusomeizeCreate: isCustomizeCreate, + }), + ); + }; + + const templateWrap = (templateSchema, { item }) => { + const schema = createCreateFormBlockUISchema({ + isCusomeizeCreate: isCustomizeCreate, + dataSource: item.dataSource, + templateSchema: templateSchema, + collectionName: item.name, + }); + if (item.template && item.mode === 'reference') { + schema['x-template-key'] = item.template.key; + } + return schema; + }; + + return { + createFormBlock, + templateWrap, + }; +}; diff --git a/packages/core/client/src/modules/blocks/data-blocks/grid-card/GridCardBlockInitializer.tsx b/packages/core/client/src/modules/blocks/data-blocks/grid-card/GridCardBlockInitializer.tsx index c0d4c2b9e..6bfaa329c 100644 --- a/packages/core/client/src/modules/blocks/data-blocks/grid-card/GridCardBlockInitializer.tsx +++ b/packages/core/client/src/modules/blocks/data-blocks/grid-card/GridCardBlockInitializer.tsx @@ -2,9 +2,9 @@ import { OrderedListOutlined } from '@ant-design/icons'; import React from 'react'; import { useSchemaInitializer, useSchemaInitializerItem } from '../../../../application'; import { useCollectionManager_deprecated } from '../../../../collection-manager'; -import { createGridCardBlockSchema } from './createGridCardBlockSchema'; import { DataBlockInitializer } from '../../../../schema-initializer/items/DataBlockInitializer'; import { Collection, CollectionFieldOptions } from '../../../../data-source/collection/Collection'; +import { createGridCardBlockUISchema } from './createGridCardBlockUISchema'; export const GridCardBlockInitializer = ({ filterCollections, @@ -33,26 +33,19 @@ export const GridCardBlockInitializer = ({ ) => any; showAssociationFields?: boolean; }) => { - const { insert } = useSchemaInitializer(); - const { getCollection } = useCollectionManager_deprecated(); const itemConfig = useSchemaInitializerItem(); + const { createGridCardBlock } = useCreateGridCardBlock(); return ( } componentType={'GridCard'} - onCreateBlockSchema={async ({ item }) => { + onCreateBlockSchema={async (options) => { if (createBlockSchema) { - return createBlockSchema({ item }); + return createBlockSchema(options); } - const collection = getCollection(item.name, item.dataSource); - const schema = createGridCardBlockSchema({ - collectionName: item.name, - dataSource: item.dataSource, - rowKey: collection.filterTargetKey || 'id', - }); - insert(schema); + createGridCardBlock(options); }} onlyCurrentDataSource={onlyCurrentDataSource} hideSearch={hideSearch} @@ -61,3 +54,20 @@ export const GridCardBlockInitializer = ({ /> ); }; + +export const useCreateGridCardBlock = () => { + const { insert } = useSchemaInitializer(); + const { getCollection } = useCollectionManager_deprecated(); + + const createGridCardBlock = ({ item }) => { + const collection = getCollection(item.name, item.dataSource); + const schema = createGridCardBlockUISchema({ + collectionName: item.name, + dataSource: item.dataSource, + rowKey: collection.filterTargetKey || 'id', + }); + insert(schema); + }; + + return { createGridCardBlock }; +}; diff --git a/packages/core/client/src/modules/blocks/data-blocks/grid-card/__tests__/createGridCardBlockSchema.test.ts b/packages/core/client/src/modules/blocks/data-blocks/grid-card/__tests__/createGridCardBlockSchema.test.ts index 11164efdc..93a68ce5e 100644 --- a/packages/core/client/src/modules/blocks/data-blocks/grid-card/__tests__/createGridCardBlockSchema.test.ts +++ b/packages/core/client/src/modules/blocks/data-blocks/grid-card/__tests__/createGridCardBlockSchema.test.ts @@ -1,4 +1,4 @@ -import { createGridCardBlockSchema } from '../createGridCardBlockSchema'; +import { createGridCardBlockSchema } from '../createGridCardBlockUISchema'; describe('createGridCardBlockSchema', () => { test('should return the correct schema', () => { diff --git a/packages/core/client/src/modules/blocks/data-blocks/grid-card/createGridCardBlockSchema.ts b/packages/core/client/src/modules/blocks/data-blocks/grid-card/createGridCardBlockUISchema.ts similarity index 97% rename from packages/core/client/src/modules/blocks/data-blocks/grid-card/createGridCardBlockSchema.ts rename to packages/core/client/src/modules/blocks/data-blocks/grid-card/createGridCardBlockUISchema.ts index d2921b4e1..c355742f6 100644 --- a/packages/core/client/src/modules/blocks/data-blocks/grid-card/createGridCardBlockSchema.ts +++ b/packages/core/client/src/modules/blocks/data-blocks/grid-card/createGridCardBlockUISchema.ts @@ -1,6 +1,6 @@ import { ISchema } from '@tachybase/schema'; -export const createGridCardBlockSchema = (options: { +export const createGridCardBlockUISchema = (options: { dataSource: string; collectionName?: string; association?: string; diff --git a/packages/core/client/src/modules/blocks/data-blocks/list/ListBlockInitializer.tsx b/packages/core/client/src/modules/blocks/data-blocks/list/ListBlockInitializer.tsx index c73b94654..8c9359397 100644 --- a/packages/core/client/src/modules/blocks/data-blocks/list/ListBlockInitializer.tsx +++ b/packages/core/client/src/modules/blocks/data-blocks/list/ListBlockInitializer.tsx @@ -2,9 +2,9 @@ import { OrderedListOutlined } from '@ant-design/icons'; import React from 'react'; import { useSchemaInitializer, useSchemaInitializerItem } from '../../../../application'; import { useCollectionManager_deprecated } from '../../../../collection-manager'; -import { createListBlockSchema } from './createListBlockSchema'; import { DataBlockInitializer } from '../../../../schema-initializer/items/DataBlockInitializer'; import { Collection, CollectionFieldOptions } from '../../../../data-source/collection/Collection'; +import { createListBlockUISchema } from './createListBlockUISchema'; export const ListBlockInitializer = ({ filterCollections, @@ -33,26 +33,20 @@ export const ListBlockInitializer = ({ ) => any; showAssociationFields?: boolean; }) => { - const { getCollection } = useCollectionManager_deprecated(); - const { insert } = useSchemaInitializer(); const itemConfig = useSchemaInitializerItem(); + const { createListBlock } = useCreateListBlock(); + return ( } componentType={'List'} - onCreateBlockSchema={async ({ item }) => { + onCreateBlockSchema={async (options) => { if (createBlockSchema) { - return createBlockSchema({ item }); + return createBlockSchema(options); } - const collection = getCollection(item.name, item.dataSource); - const schema = createListBlockSchema({ - collectionName: item.name, - dataSource: item.dataSource, - rowKey: collection.filterTargetKey || 'id', - }); - insert(schema); + createListBlock(options); }} onlyCurrentDataSource={onlyCurrentDataSource} hideSearch={hideSearch} @@ -61,3 +55,20 @@ export const ListBlockInitializer = ({ /> ); }; + +export const useCreateListBlock = () => { + const { getCollection } = useCollectionManager_deprecated(); + const { insert } = useSchemaInitializer(); + + const createListBlock = ({ item }) => { + const collection = getCollection(item.name, item.dataSource); + const schema = createListBlockUISchema({ + collectionName: item.name, + dataSource: item.dataSource, + rowKey: collection.filterTargetKey || 'id', + }); + insert(schema); + }; + + return { createListBlock }; +}; diff --git a/packages/core/client/src/modules/blocks/data-blocks/list/__tests__/createListBlockSchema.test.ts b/packages/core/client/src/modules/blocks/data-blocks/list/__tests__/createListBlockSchema.test.ts index 20772fe13..a61268ec7 100644 --- a/packages/core/client/src/modules/blocks/data-blocks/list/__tests__/createListBlockSchema.test.ts +++ b/packages/core/client/src/modules/blocks/data-blocks/list/__tests__/createListBlockSchema.test.ts @@ -1,4 +1,4 @@ -import { createListBlockSchema } from '../createListBlockSchema'; +import { createListBlockSchema } from '../createListBlockUISchema'; describe('createListBlockSchema', () => { test('should return the correct schema', () => { diff --git a/packages/core/client/src/modules/blocks/data-blocks/list/createListBlockSchema.ts b/packages/core/client/src/modules/blocks/data-blocks/list/createListBlockUISchema.ts similarity index 97% rename from packages/core/client/src/modules/blocks/data-blocks/list/createListBlockSchema.ts rename to packages/core/client/src/modules/blocks/data-blocks/list/createListBlockUISchema.ts index 458bdd7f5..ec6c44b1f 100644 --- a/packages/core/client/src/modules/blocks/data-blocks/list/createListBlockSchema.ts +++ b/packages/core/client/src/modules/blocks/data-blocks/list/createListBlockUISchema.ts @@ -1,6 +1,6 @@ import { ISchema } from '@tachybase/schema'; -export const createListBlockSchema = (options: { +export const createListBlockUISchema = (options: { dataSource: string; collectionName?: string; association?: string; diff --git a/packages/core/client/src/modules/blocks/data-blocks/table/TableBlockInitializer.tsx b/packages/core/client/src/modules/blocks/data-blocks/table/TableBlockInitializer.tsx index 374293f46..492a80004 100644 --- a/packages/core/client/src/modules/blocks/data-blocks/table/TableBlockInitializer.tsx +++ b/packages/core/client/src/modules/blocks/data-blocks/table/TableBlockInitializer.tsx @@ -28,26 +28,19 @@ export const TableBlockInitializer = ({ ) => any; showAssociationFields?: boolean; }) => { - const { insert } = useSchemaInitializer(); - const { getCollection } = useCollectionManager_deprecated(); + const { createTableBlock } = useCreateTableBlock(); const itemConfig = useSchemaInitializerItem(); return ( } componentType={'Table'} - onCreateBlockSchema={async ({ item }) => { + onCreateBlockSchema={async (options) => { if (createBlockSchema) { - return createBlockSchema({ item }); + return createBlockSchema(options); } - const collection = getCollection(item.name, item.dataSource); - const schema = createTableBlockUISchema({ - collectionName: item.name, - dataSource: item.dataSource, - rowKey: collection.filterTargetKey || 'id', - }); - insert(schema); + createTableBlock(options); }} onlyCurrentDataSource={onlyCurrentDataSource} hideSearch={hideSearch} @@ -56,3 +49,20 @@ export const TableBlockInitializer = ({ /> ); }; + +export const useCreateTableBlock = () => { + const { insert } = useSchemaInitializer(); + const { getCollection } = useCollectionManager_deprecated(); + + const createTableBlock = ({ item }) => { + const collection = getCollection(item.name, item.dataSource); + const schema = createTableBlockUISchema({ + collectionName: item.name, + dataSource: item.dataSource, + rowKey: collection.filterTargetKey || 'id', + }); + insert(schema); + }; + + return { createTableBlock }; +}; diff --git a/packages/core/client/src/schema-initializer/buttons/RecordBlockInitializers.tsx b/packages/core/client/src/schema-initializer/buttons/RecordBlockInitializers.tsx index c8c227886..17fa7f53d 100644 --- a/packages/core/client/src/schema-initializer/buttons/RecordBlockInitializers.tsx +++ b/packages/core/client/src/schema-initializer/buttons/RecordBlockInitializers.tsx @@ -11,10 +11,16 @@ import { useCreateAssociationListBlock, useCreateAssociationTableBlock, useCreateEditFormBlock, + useCreateFormBlock, + useCreateTableBlock, } from '../..'; import { CompatibleSchemaInitializer } from '../../application/schema-initializer/CompatibleSchemaInitializer'; +import { useCreateDetailsBlock } from '../../modules/blocks/data-blocks/details-multi/DetailsBlockInitializer'; + import { gridRowColWrap } from '../utils'; import { useCreateSingleDetailsSchema } from '../../modules/blocks/data-blocks/details-single/RecordReadPrettyFormBlockInitializer'; +import { useCreateGridCardBlock } from '../../modules/blocks/data-blocks/grid-card/GridCardBlockInitializer'; +import { useCreateListBlock } from '../../modules/blocks/data-blocks/list/ListBlockInitializer'; const recursiveParent = (schema: Schema) => { if (!schema) return null; @@ -52,9 +58,13 @@ function useRecordBlocks() { createAssociationDetailsWithoutPagination, templateWrap: templateWrapOfAssociationDetailsWithoutPagination, } = useCreateAssociationDetailsWithoutPagination(); + const { createDetailsBlock } = useCreateDetailsBlock(); const collectionsNeedToDisplay = [currentCollection, ...collectionsWithView]; const createBlockSchema = useCallback( - ({ item }) => { + ({ item, fromOthersInPopup }) => { + if (fromOthersInPopup) { + return createDetailsBlock({ item }); + } if (item.associationField) { if (['hasOne', 'belongsTo'].includes(item.associationField.type)) { return createAssociationDetailsWithoutPagination({ item }); @@ -63,7 +73,12 @@ function useRecordBlocks() { } return createSingleDetailsSchema({ item }); }, - [createAssociationDetailsBlock, createAssociationDetailsWithoutPagination, createSingleDetailsSchema], + [ + createAssociationDetailsBlock, + createAssociationDetailsWithoutPagination, + createDetailsBlock, + createSingleDetailsSchema, + ], ); return { filterCollections({ collection, associationField }) { @@ -103,7 +118,7 @@ function useRecordBlocks() { dataSource: collection.dataSource, useComponentProps() { const currentCollection = useCollection_deprecated(); - const { createEditFormBlock, templateWrap } = useCreateEditFormBlock(); + const { createEditFormBlock, templateWrap: templateWrapEdit } = useCreateEditFormBlock(); const collectionsNeedToDisplay = [currentCollection, ...collectionsWithView]; return { @@ -117,7 +132,8 @@ function useRecordBlocks() { hideSearch: true, componentType: 'FormItem', createBlockSchema: createEditFormBlock, - templateWrap: templateWrap, + templateWrap: templateWrapEdit, + hideOtherRecordsInPopup: true, showAssociationFields: true, }; }, @@ -133,6 +149,7 @@ function useRecordBlocks() { dataSource: collection.dataSource, useComponentProps() { const { createAssociationFormBlock, templateWrap } = useCreateAssociationFormBlock(); + const { createFormBlock, templateWrap: templateWrapCollection } = useCreateFormBlock(); return { filterCollections({ collection, associationField }) { if (associationField) { @@ -143,38 +160,29 @@ function useRecordBlocks() { onlyCurrentDataSource: true, hideSearch: true, componentType: 'FormItem', - createBlockSchema: createAssociationFormBlock, - templateWrap: templateWrap, + createBlockSchema: ({ item, fromOthersInPopup }) => { + if (fromOthersInPopup) { + return createFormBlock({ item }); + } + createAssociationFormBlock({ item }); + }, + templateWrap: (templateSchema, { item, fromOthersInPopup }) => { + if (fromOthersInPopup) { + return templateWrapCollection(templateSchema, { item }); + } + templateWrap(templateSchema, { item }); + }, showAssociationFields: true, }; }, - useVisible() { - const collection = useCollection(); - return useMemo( - () => - collection.fields.some( - (field) => canMakeAssociationBlock(field) && ['hasMany', 'belongsToMany'].includes(field.type), - ), - [collection.fields], - ); - }, }, { name: 'table', title: '{{t("Table")}}', Component: 'TableBlockInitializer', - useVisible() { - const collection = useCollection(); - return useMemo( - () => - collection.fields.some( - (field) => canMakeAssociationBlock(field) && ['hasMany', 'belongsToMany'].includes(field.type), - ), - [collection.fields], - ); - }, useComponentProps() { const { createAssociationTableBlock } = useCreateAssociationTableBlock(); + const { createTableBlock } = useCreateTableBlock(); return { hideSearch: true, @@ -185,7 +193,12 @@ function useRecordBlocks() { } return false; }, - createBlockSchema: createAssociationTableBlock, + createBlockSchema: ({ item, fromOthersInPopup }) => { + if (fromOthersInPopup) { + return createTableBlock({ item }); + } + createAssociationTableBlock({ item }); + }, showAssociationFields: true, }; }, @@ -194,18 +207,9 @@ function useRecordBlocks() { name: 'list', title: '{{t("List")}}', Component: 'ListBlockInitializer', - useVisible() { - const collection = useCollection(); - return useMemo( - () => - collection.fields.some( - (field) => canMakeAssociationBlock(field) && ['hasMany', 'belongsToMany'].includes(field.type), - ), - [collection.fields], - ); - }, useComponentProps() { const { createAssociationListBlock } = useCreateAssociationListBlock(); + const { createListBlock } = useCreateListBlock(); return { hideSearch: true, @@ -216,7 +220,12 @@ function useRecordBlocks() { } return false; }, - createBlockSchema: createAssociationListBlock, + createBlockSchema: ({ item, fromOthersInPopup }) => { + if (fromOthersInPopup) { + return createListBlock({ item }); + } + createAssociationListBlock({ item }); + }, showAssociationFields: true, }; }, @@ -225,18 +234,9 @@ function useRecordBlocks() { name: 'gridCard', title: '{{t("Grid Card")}}', Component: 'GridCardBlockInitializer', - useVisible() { - const collection = useCollection(); - return useMemo( - () => - collection.fields.some( - (field) => canMakeAssociationBlock(field) && ['hasMany', 'belongsToMany'].includes(field.type), - ), - [collection.fields], - ); - }, useComponentProps() { const { createAssociationGridCardBlock } = useCreateAssociationGridCardBlock(); + const { createGridCardBlock } = useCreateGridCardBlock(); return { hideSearch: true, @@ -247,7 +247,12 @@ function useRecordBlocks() { } return false; }, - createBlockSchema: createAssociationGridCardBlock, + createBlockSchema: ({ item, fromOthersInPopup }) => { + if (fromOthersInPopup) { + return createGridCardBlock({ item }); + } + createAssociationGridCardBlock({ item }); + }, showAssociationFields: true, }; }, diff --git a/packages/core/client/src/schema-initializer/items/DataBlockInitializer.tsx b/packages/core/client/src/schema-initializer/items/DataBlockInitializer.tsx index ab91dd137..8023c907f 100644 --- a/packages/core/client/src/schema-initializer/items/DataBlockInitializer.tsx +++ b/packages/core/client/src/schema-initializer/items/DataBlockInitializer.tsx @@ -261,8 +261,10 @@ export interface DataBlockInitializerProps { templateSchema: any, { item, + fromOthersInPopup, }: { item: any; + fromOthersInPopup?: boolean; }, ) => any; onCreateBlockSchema?: (args: any) => void; @@ -279,6 +281,14 @@ export interface DataBlockInitializerProps { /** 如果只有一项数据表时,不显示 children 列表 */ hideChildrenIfSingleCollection?: boolean; items?: ReturnType[]; + /** + * 是否是点击弹窗中的 Others 选项进入的 + */ + fromOthersInPopup?: boolean; + /** + * 隐藏弹窗中的 Other records 选项 + */ + hideOtherRecordsInPopup?: boolean; } export const DataBlockInitializer = (props: DataBlockInitializerProps) => { @@ -296,6 +306,8 @@ export const DataBlockInitializer = (props: DataBlockInitializerProps) => { hideChildrenIfSingleCollection, filterDataSource, items: itemsFromProps, + fromOthersInPopup, + hideOtherRecordsInPopup, } = props; const { insert, setVisible } = useSchemaInitializer(); const compile = useCompile(); @@ -304,15 +316,15 @@ export const DataBlockInitializer = (props: DataBlockInitializerProps) => { async ({ item }) => { if (item.template) { const s = await getTemplateSchemaByMode(item); - templateWrap ? insert(templateWrap(s, { item })) : insert(s); + templateWrap ? insert(templateWrap(s, { item, fromOthersInPopup })) : insert(s); } else { if (onCreateBlockSchema) { - onCreateBlockSchema({ item }); + onCreateBlockSchema({ item, fromOthersInPopup }); } } setVisible(false); }, - [getTemplateSchemaByMode, insert, onCreateBlockSchema, setVisible, templateWrap], + [fromOthersInPopup, getTemplateSchemaByMode, insert, onCreateBlockSchema, setVisible, templateWrap], ); const items = itemsFromProps || @@ -324,6 +336,7 @@ export const DataBlockInitializer = (props: DataBlockInitializerProps) => { onlyCurrentDataSource, showAssociationFields, dataBlockInitializerProps: props, + hideOtherRecordsInPopup, }); const getMenuItems = useGetSchemaInitializerMenuItems(onClick); const childItems = useMemo(() => { diff --git a/packages/core/client/src/schema-initializer/items/RecordAssociationGridCardBlockInitializer.tsx b/packages/core/client/src/schema-initializer/items/RecordAssociationGridCardBlockInitializer.tsx index 2be266619..d36a87ab9 100644 --- a/packages/core/client/src/schema-initializer/items/RecordAssociationGridCardBlockInitializer.tsx +++ b/packages/core/client/src/schema-initializer/items/RecordAssociationGridCardBlockInitializer.tsx @@ -5,7 +5,7 @@ import { useCollectionManager_deprecated } from '../../collection-manager'; import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } from '../../application'; import { useSchemaTemplateManager } from '../../schema-templates'; import { useRecordCollectionDataSourceItems } from '../utils'; -import { createGridCardBlockSchema } from '../../modules/blocks/data-blocks/grid-card/createGridCardBlockSchema'; +import { createGridCardBlockUISchema } from '../../modules/blocks/data-blocks/grid-card/createGridCardBlockUISchema'; /** * @deprecated @@ -30,7 +30,7 @@ export const RecordAssociationGridCardBlockInitializer = () => { insert(s); } else { insert( - createGridCardBlockSchema({ + createGridCardBlockUISchema({ rowKey: collection.filterTargetKey, dataSource: collection.dataSource, association: resource, @@ -53,7 +53,7 @@ export function useCreateAssociationGridCardBlock() { const collection = getCollection(field.target); insert( - createGridCardBlockSchema({ + createGridCardBlockUISchema({ rowKey: collection.filterTargetKey, dataSource: collection.dataSource, association: `${field.collectionName}.${field.name}`, diff --git a/packages/core/client/src/schema-initializer/items/RecordAssociationListBlockInitializer.tsx b/packages/core/client/src/schema-initializer/items/RecordAssociationListBlockInitializer.tsx index 4e47b3e70..377708770 100644 --- a/packages/core/client/src/schema-initializer/items/RecordAssociationListBlockInitializer.tsx +++ b/packages/core/client/src/schema-initializer/items/RecordAssociationListBlockInitializer.tsx @@ -5,7 +5,7 @@ import { SchemaInitializerItem, useSchemaInitializer, useSchemaInitializerItem } import { useCollectionManager_deprecated } from '../../collection-manager'; import { useSchemaTemplateManager } from '../../schema-templates'; import { useRecordCollectionDataSourceItems } from '../utils'; -import { createListBlockSchema } from '../../modules/blocks/data-blocks/list/createListBlockSchema'; +import { createListBlockUISchema } from '../../modules/blocks/data-blocks/list/createListBlockUISchema'; export const RecordAssociationListBlockInitializer = () => { const itemConfig = useSchemaInitializerItem(); @@ -27,7 +27,7 @@ export const RecordAssociationListBlockInitializer = () => { insert(s); } else { insert( - createListBlockSchema({ + createListBlockUISchema({ rowKey: collection.filterTargetKey, dataSource: collection.dataSource, association: resource, @@ -50,7 +50,7 @@ export function useCreateAssociationListBlock() { const collection = getCollection(field.target); insert( - createListBlockSchema({ + createListBlockUISchema({ rowKey: collection.filterTargetKey, dataSource: collection.dataSource, association: `${field.collectionName}.${field.name}`, diff --git a/packages/core/client/src/schema-initializer/utils.ts b/packages/core/client/src/schema-initializer/utils.ts index 5ef9fde7c..dfa3981b3 100644 --- a/packages/core/client/src/schema-initializer/utils.ts +++ b/packages/core/client/src/schema-initializer/utils.ts @@ -842,6 +842,7 @@ export const useCollectionDataSourceItems = ({ showAssociationFields, filterDataSource, dataBlockInitializerProps, + hideOtherRecordsInPopup, }: { componentName; filter?: (options: { collection?: Collection; associationField?: CollectionFieldOptions }) => boolean; @@ -849,6 +850,10 @@ export const useCollectionDataSourceItems = ({ showAssociationFields?: boolean; filterDataSource?: (dataSource?: DataSource) => boolean; dataBlockInitializerProps?: any; + /** + * 隐藏弹窗中的 Other records 选项 + */ + hideOtherRecordsInPopup?: boolean; }) => { const { t } = useTranslation(); const dm = useDataSourceManager(); @@ -936,19 +941,56 @@ export const useCollectionDataSourceItems = ({ ], }, }; + const componentTypeMap = { + ReadPrettyFormItem: 'Details', + }; + const otherRecords = { + name: 'otherRecords', + Component: DataBlockInitializer, + // 目的是使点击无效 + onClick() {}, + componentProps: { + icon: null, + title: t('Other records'), + name: 'otherRecords', + showAssociationFields: false, + onlyCurrentDataSource: false, + hideChildrenIfSingleCollection: false, + onCreateBlockSchema: dataBlockInitializerProps.onCreateBlockSchema, + fromOthersInPopup: true, + componentType: componentTypeMap[componentName] || componentName, + filter({ collection: c, associationField }) { + return true; + }, + }, + }; + let children; + const _associationRecords = associationFields.length ? associationRecords : null; 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; + if (hideOtherRecordsInPopup) { + children = [currentRecord, _associationRecords]; + } else { + children = [currentRecord, _associationRecords, otherRecords]; + } + } else if (noAssociationMenu[0].children.length) { + if (hideOtherRecordsInPopup) { + // 当可选数据表只有一个时,实现只点击一次区块 menu 就能创建区块 + if (noAssociationMenu[0].children.length <= 1) { + noAssociationMenu[0].children = (noAssociationMenu[0].children[0]?.children as any) || []; + return noAssociationMenu; + } + children = [currentRecord]; + } else { + children = [currentRecord, otherRecords]; } - children = [currentRecord]; } else { - children = [associationRecords]; + if (hideOtherRecordsInPopup) { + children = [_associationRecords]; + } else { + children = [_associationRecords, otherRecords]; + } } return [ @@ -956,10 +998,19 @@ export const useCollectionDataSourceItems = ({ name: 'records', label: t('Records'), type: 'subMenu', - children, + children: children.filter(Boolean), }, ]; - }, [associationFields, collection.dataSource, collection.name, dataBlockInitializerProps, noAssociationMenu, t]); + }, [ + associationFields, + collection.dataSource, + collection.name, + componentName, + dataBlockInitializerProps, + hideOtherRecordsInPopup, + noAssociationMenu, + t, + ]); } return noAssociationMenu; diff --git a/packages/plugins/@nocobase/plugin-calendar/src/client/index.tsx b/packages/plugins/@nocobase/plugin-calendar/src/client/index.tsx index e45f6227b..bf19d1cf5 100644 --- a/packages/plugins/@nocobase/plugin-calendar/src/client/index.tsx +++ b/packages/plugins/@nocobase/plugin-calendar/src/client/index.tsx @@ -1,8 +1,9 @@ -import { Plugin, canMakeAssociationBlock, useCollection } from '@nocobase/client'; +import { Plugin } from '@nocobase/client'; import { generateNTemplate } from '../locale'; import { CalendarV2 } from './calendar'; import { calendarBlockSettings } from './calendar/Calender.Settings'; import { CalendarCollectionTemplate } from './collection-templates/calendar'; +import { useCalendarBlockDecoratorProps } from './hooks/useCalendarBlockDecoratorProps'; import { CalendarBlockProvider, useCalendarBlockProps } from './schema-initializer/CalendarBlockProvider'; import { CalendarActionInitializers_deprecated, @@ -14,9 +15,8 @@ import { CalendarBlockInitializer, RecordAssociationCalendarBlockInitializer, useCreateAssociationCalendarBlock, + useCreateCalendarBlock, } from './schema-initializer/items'; -import { useMemo } from 'react'; -import { useCalendarBlockDecoratorProps } from './hooks/useCalendarBlockDecoratorProps'; export class PluginCalendarClient extends Plugin { async load() { @@ -28,18 +28,9 @@ export class PluginCalendarClient extends Plugin { this.app.schemaInitializerManager.addItem('popup:common:addBlock', 'dataBlocks.calendar', { title: generateNTemplate('Calendar'), Component: 'CalendarBlockInitializer', - useVisible() { - const collection = useCollection(); - return useMemo( - () => - collection.fields.some( - (field) => canMakeAssociationBlock(field) && ['hasMany', 'belongsToMany'].includes(field.type), - ), - [collection.fields], - ); - }, useComponentProps() { const { createAssociationCalendarBlock } = useCreateAssociationCalendarBlock(); + const { createCalendarBlock } = useCreateCalendarBlock(); return { onlyCurrentDataSource: true, @@ -49,7 +40,12 @@ export class PluginCalendarClient extends Plugin { } return false; }, - createBlockSchema: createAssociationCalendarBlock, + createBlockSchema: ({ item, fromOthersInPopup }) => { + if (fromOthersInPopup) { + return createCalendarBlock({ item }); + } + createAssociationCalendarBlock({ item }); + }, showAssociationFields: true, hideSearch: true, }; diff --git a/packages/plugins/@nocobase/plugin-calendar/src/client/schema-initializer/items/CalendarBlockInitializer.tsx b/packages/plugins/@nocobase/plugin-calendar/src/client/schema-initializer/items/CalendarBlockInitializer.tsx index 82170171f..6f84e13cd 100644 --- a/packages/plugins/@nocobase/plugin-calendar/src/client/schema-initializer/items/CalendarBlockInitializer.tsx +++ b/packages/plugins/@nocobase/plugin-calendar/src/client/schema-initializer/items/CalendarBlockInitializer.tsx @@ -30,79 +30,19 @@ export const CalendarBlockInitializer = ({ createBlockSchema?: (options: any) => any; showAssociationFields?: boolean; }) => { - const { insert } = useSchemaInitializer(); - const { t } = useTranslation(); - const { getCollectionField, getCollectionFieldsOptions } = useCollectionManager_deprecated(); - const options = useContext(SchemaOptionsContext); - const { theme } = useGlobalTheme(); const itemConfig = useSchemaInitializerItem(); + const { createCalendarBlock } = useCreateCalendarBlock(); return ( } - onCreateBlockSchema={async ({ item }) => { + onCreateBlockSchema={async (options) => { if (createBlockSchema) { - return createBlockSchema({ item }); + return createBlockSchema(options); } - - const stringFieldsOptions = getCollectionFieldsOptions(item.name, 'string', { dataSource: item.dataSource }); - const dateFieldsOptions = getCollectionFieldsOptions(item.name, 'date', { - association: ['o2o', 'obo', 'oho', 'm2o'], - dataSource: item.dataSource, - }); - - const values = await FormDialog( - t('Create calendar block'), - () => { - return ( - - - - - - ); - }, - theme, - ).open({ - initialValues: {}, - }); - insert( - createCalendarBlockUISchema({ - collectionName: item.name, - dataSource: item.dataSource, - fieldNames: { - ...values, - }, - }), - ); + createCalendarBlock(options); }} onlyCurrentDataSource={onlyCurrentDataSource} hideSearch={hideSearch} @@ -111,3 +51,72 @@ export const CalendarBlockInitializer = ({ /> ); }; + +export const useCreateCalendarBlock = () => { + const { insert } = useSchemaInitializer(); + const { t } = useTranslation(); + const { getCollectionField, getCollectionFieldsOptions } = useCollectionManager_deprecated(); + const options = useContext(SchemaOptionsContext); + const { theme } = useGlobalTheme(); + + const createCalendarBlock = async ({ item }) => { + const stringFieldsOptions = getCollectionFieldsOptions(item.name, 'string', { dataSource: item.dataSource }); + const dateFieldsOptions = getCollectionFieldsOptions(item.name, 'date', { + association: ['o2o', 'obo', 'oho', 'm2o'], + dataSource: item.dataSource, + }); + + const values = await FormDialog( + t('Create calendar block'), + () => { + return ( + + + + + + ); + }, + theme, + ).open({ + initialValues: {}, + }); + insert( + createCalendarBlockUISchema({ + collectionName: item.name, + dataSource: item.dataSource, + fieldNames: { + ...values, + }, + }), + ); + }; + + return { createCalendarBlock }; +};