From ef097bd450642e87cc1c2da40346f3c6644156e1 Mon Sep 17 00:00:00 2001 From: Chareice Date: Mon, 11 Mar 2024 13:04:49 +0800 Subject: [PATCH 01/11] fix: acl snippet value --- packages/plugins/@nocobase/plugin-acl/src/client/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/plugins/@nocobase/plugin-acl/src/client/index.ts b/packages/plugins/@nocobase/plugin-acl/src/client/index.ts index 8418f4a60..172585bc1 100644 --- a/packages/plugins/@nocobase/plugin-acl/src/client/index.ts +++ b/packages/plugins/@nocobase/plugin-acl/src/client/index.ts @@ -10,7 +10,7 @@ class ACLPlugin extends Plugin { title: '{{t("Roles & Permissions")}}', icon: 'LockOutlined', Component: RolesManagement, - aclSnippet: 'pm.roles', + aclSnippet: 'pm.acl.roles', sort: 3, }); } From ba2467c9bfd6e0c6acf8d790bd2cf87d00791dee Mon Sep 17 00:00:00 2001 From: katherinehhh Date: Mon, 11 Mar 2024 16:52:14 +0800 Subject: [PATCH 02/11] fix: assign field values modal shuold support maskClosable --- .../antd/action/Action.Designer.tsx | 2 +- .../src/client/BulkUpdateAction.Settings.tsx | 15 +++------------ 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/packages/core/client/src/schema-component/antd/action/Action.Designer.tsx b/packages/core/client/src/schema-component/antd/action/Action.Designer.tsx index 19ac2679c..cdd890d9f 100644 --- a/packages/core/client/src/schema-component/antd/action/Action.Designer.tsx +++ b/packages/core/client/src/schema-component/antd/action/Action.Designer.tsx @@ -167,7 +167,7 @@ export function AssignedFieldValues() { false}> Date: Mon, 11 Mar 2024 16:57:37 +0800 Subject: [PATCH 03/11] fix: inheritance cache bug (#3669) --- .../mixins/InheritanceCollectionMixin.ts | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/packages/core/client/src/collection-manager/mixins/InheritanceCollectionMixin.ts b/packages/core/client/src/collection-manager/mixins/InheritanceCollectionMixin.ts index 208fa0a31..fb199d692 100644 --- a/packages/core/client/src/collection-manager/mixins/InheritanceCollectionMixin.ts +++ b/packages/core/client/src/collection-manager/mixins/InheritanceCollectionMixin.ts @@ -16,8 +16,8 @@ export class InheritanceCollectionMixin extends Collection { protected foreignKeyFields: CollectionFieldOptions[]; getParentCollectionsName() { - if (this.parentCollectionsName?.length) { - return this.parentCollectionsName; + if (this.parentCollectionsName) { + return this.parentCollectionsName.slice(); } const parents: string[] = []; @@ -41,8 +41,8 @@ export class InheritanceCollectionMixin extends Collection { } getParentCollections() { - if (this.parentCollections?.length) { - return this.parentCollections; + if (this.parentCollections) { + return this.parentCollections.slice(); } this.parentCollections = this.getParentCollectionsName().map((collectionName) => { return this.collectionManager.getCollection(collectionName); @@ -52,8 +52,8 @@ export class InheritanceCollectionMixin extends Collection { getChildrenCollectionsName(isSupportView = false) { const cacheKey = isSupportView ? 'supportView' : 'notSupportView'; - if (this.childrenCollectionsName[cacheKey]?.length) { - return this.childrenCollectionsName[cacheKey]; + if (this.childrenCollectionsName[cacheKey]) { + return this.childrenCollectionsName[cacheKey].slice(); } const children: string[] = []; @@ -86,8 +86,8 @@ export class InheritanceCollectionMixin extends Collection { getChildrenCollections(isSupportView = false) { const cacheKey = isSupportView ? 'supportView' : 'notSupportView'; - if (this.childrenCollections[cacheKey]?.length) { - return this.childrenCollections[cacheKey]; + if (this.childrenCollections[cacheKey]) { + return this.childrenCollections[cacheKey].slice(); } this.childrenCollections[cacheKey] = this.getChildrenCollectionsName(isSupportView).map((collectionName) => { return this.collectionManager.getCollection(collectionName); @@ -96,8 +96,8 @@ export class InheritanceCollectionMixin extends Collection { } getInheritedFields() { - if (this.inheritsFields?.length) { - return this.inheritsFields; + if (this.inheritsFields) { + return this.inheritsFields.slice(); } const parentCollections = this.getParentCollectionsName(); @@ -155,8 +155,8 @@ export class InheritanceCollectionMixin extends Collection { } getAllCollectionsInheritChain() { - if (this.allCollectionsInheritChain?.length) { - return this.allCollectionsInheritChain; + if (this.allCollectionsInheritChain) { + return this.allCollectionsInheritChain.slice(); } const collectionsInheritChain = [this.name]; @@ -197,8 +197,8 @@ export class InheritanceCollectionMixin extends Collection { } getInheritCollectionsChain() { - if (this.inheritCollectionsChain?.length) { - return this.inheritCollectionsChain; + if (this.inheritCollectionsChain) { + return this.inheritCollectionsChain.slice(); } const collectionsInheritChain = [this.name]; const getInheritChain = (name: string) => { @@ -225,8 +225,8 @@ export class InheritanceCollectionMixin extends Collection { } getAllFields(predicate?: GetCollectionFieldPredicate) { - if (this.allFields?.length) { - return this.allFields; + if (this.allFields) { + return this.allFields.slice(); } const currentFields = this.getCurrentFields(); const inheritedFields = this.getInheritedFields(); @@ -240,8 +240,8 @@ export class InheritanceCollectionMixin extends Collection { } getForeignKeyFields() { - if (this.foreignKeyFields?.length) { - return this.foreignKeyFields; + if (this.foreignKeyFields) { + return this.foreignKeyFields.slice(); } const currentFields = this.getCurrentFields(); const inheritedFields = this.getInheritedFields(); From 3da2a8af920a7d106af03d4798d9c0fe858b4cbe Mon Sep 17 00:00:00 2001 From: ChengLei Shao Date: Mon, 11 Mar 2024 19:37:48 +0800 Subject: [PATCH 04/11] fix: init scope value when all data is null value (#3674) --- .../src/__tests__/fields/sort-field.test.ts | 35 +++++++++++++++++++ .../core/database/src/fields/sort-field.ts | 18 +++++++--- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/packages/core/database/src/__tests__/fields/sort-field.test.ts b/packages/core/database/src/__tests__/fields/sort-field.test.ts index e53edf6a5..dbf0efffc 100644 --- a/packages/core/database/src/__tests__/fields/sort-field.test.ts +++ b/packages/core/database/src/__tests__/fields/sort-field.test.ts @@ -90,6 +90,41 @@ describe('string field', () => { console.log(end - begin); }); + it('should init sorted value with null scopeValue', async () => { + const Test = db.collection({ + name: 'tests', + fields: [ + { + type: 'string', + name: 'name', + }, + { + type: 'string', + name: 'group', + }, + ], + }); + + await db.sync(); + + await Test.repository.create({ + values: [ + { + group: null, + name: 'r5', + }, + { + group: null, + name: 'r6', + }, + ], + }); + + Test.setField('sort', { type: 'sort', scopeKey: 'group' }); + + await db.sync(); + }); + it('should init sorted value with scopeKey', async () => { const Test = db.collection({ name: 'tests', diff --git a/packages/core/database/src/fields/sort-field.ts b/packages/core/database/src/fields/sort-field.ts index 41cea73fc..30d9adae6 100644 --- a/packages/core/database/src/fields/sort-field.ts +++ b/packages/core/database/src/fields/sort-field.ts @@ -99,11 +99,19 @@ export class SortField extends Field { const whereClause = scopeKey && scopeValue - ? ` - WHERE ${queryInterface.quoteIdentifier(scopeKey)} IN (${scopeValue - .filter((v) => v !== null) - .map((v) => `'${v}'`) - .join(', ')})${scopeValue.includes(null) ? ` OR ${queryInterface.quoteIdentifier(scopeKey)} IS NULL` : ''}` + ? (() => { + const filteredScopeValue = scopeValue.filter((v) => v !== null); + if (filteredScopeValue.length === 0) { + return ''; + } + const initialClause = ` + WHERE ${queryInterface.quoteIdentifier(scopeKey)} IN (${filteredScopeValue.map((v) => `'${v}'`).join(', ')})`; + + const nullCheck = scopeValue.includes(null) + ? ` OR ${queryInterface.quoteIdentifier(scopeKey)} IS NULL` + : ''; + return initialClause + nullCheck; + })() : ''; if (this.collection.db.inDialect('postgres')) { From cdf9f4818f874c95e86d4391c9ed20baab7c6e48 Mon Sep 17 00:00:00 2001 From: ChengLei Shao Date: Tue, 12 Mar 2024 09:08:15 +0800 Subject: [PATCH 05/11] fix: acl should return true when resource allowed (#3675) * fix: acl should return true when resource allowed * chore: test --- packages/core/acl/src/acl.ts | 6 ++--- .../src/server/__tests__/snippets.test.ts | 24 ++++++++++++++++++- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/packages/core/acl/src/acl.ts b/packages/core/acl/src/acl.ts index d7ed1ab73..e750f663f 100644 --- a/packages/core/acl/src/acl.ts +++ b/packages/core/acl/src/acl.ts @@ -164,9 +164,9 @@ export class ACL extends EventEmitter { const snippetAllowed = aclRole.snippetAllowed(`${resource}:${action}`); - if (snippetAllowed === false) { - return null; - } + // if (snippetAllowed === false) { + // return null; + // } const fixedParams = this.fixedParamsManager.getParams(resource, action); diff --git a/packages/plugins/@nocobase/plugin-acl/src/server/__tests__/snippets.test.ts b/packages/plugins/@nocobase/plugin-acl/src/server/__tests__/snippets.test.ts index ef8891625..dd6bcaa97 100644 --- a/packages/plugins/@nocobase/plugin-acl/src/server/__tests__/snippets.test.ts +++ b/packages/plugins/@nocobase/plugin-acl/src/server/__tests__/snippets.test.ts @@ -12,7 +12,7 @@ describe('snippet', () => { await app.destroy(); }); - it('should not allow to create collections when global allow create', async () => { + it.skip('should not allow to create collections when global allow create', async () => { await app.db.getRepository('roles').create({ values: { name: 'testRole', @@ -32,4 +32,26 @@ describe('snippet', () => { expect(createCollectionResponse.statusCode).toEqual(403); }); + + it('should allowed when snippet not allowed but resource allowed', async () => { + await app.db.getRepository('roles').create({ + values: { + name: 'testRole', + strategy: { actions: ['view'] }, + snippets: ['!ui.*', '!pm', '!pm.*'], + }, + }); + + const testUser = await app.db.getRepository('users').create({ + values: { + roles: ['testRole'], + }, + }); + + const userAgent: any = app.agent().login(testUser); + + const listResp = await userAgent.resource('users').list(); + + expect(listResp.statusCode).toEqual(200); + }); }); From 4a346a41195531da7edc1bf3b3b73e0dac73bcf6 Mon Sep 17 00:00:00 2001 From: katherinehhh Date: Tue, 12 Mar 2024 09:30:38 +0800 Subject: [PATCH 06/11] fix: view collection association field foreignkey should be select (#3671) --- .../collection-manager/Configuration/components/index.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/core/client/src/collection-manager/Configuration/components/index.tsx b/packages/core/client/src/collection-manager/Configuration/components/index.tsx index eb5e4404b..5e7a60e25 100644 --- a/packages/core/client/src/collection-manager/Configuration/components/index.tsx +++ b/packages/core/client/src/collection-manager/Configuration/components/index.tsx @@ -221,11 +221,11 @@ export const ForeignKey = observer( const { getCollection } = useCollectionManager_deprecated(); const record = useRecord(); const field: any = useField(); - const { collectionName, target, type, through, name } = record; + const { collectionName, target, type, through, name, template } = record; const value = record[field.props.name]; const compile = useCompile(); const form = useForm(); - const [initialValue, setInitialValue] = useState(value || field.initialValue); + const [initialValue, setInitialValue] = useState(value || (template === 'view' ? null : field.initialValue)); useEffect(() => { const effectField = ['belongsTo'].includes(type) ? collectionName @@ -251,9 +251,10 @@ export const ForeignKey = observer( } } }, [type]); + const Compoent = template === 'view' ? Select : AutoComplete; return (
- Date: Tue, 12 Mar 2024 11:34:22 +0800 Subject: [PATCH 07/11] fix: upgrade app after restore (#3680) --- .../src/server/commands/restore-command.ts | 2 +- .../@nocobase/plugin-backup-restore/src/server/restorer.ts | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/plugins/@nocobase/plugin-backup-restore/src/server/commands/restore-command.ts b/packages/plugins/@nocobase/plugin-backup-restore/src/server/commands/restore-command.ts index 0753b5966..f8800d80f 100644 --- a/packages/plugins/@nocobase/plugin-backup-restore/src/server/commands/restore-command.ts +++ b/packages/plugins/@nocobase/plugin-backup-restore/src/server/commands/restore-command.ts @@ -62,6 +62,6 @@ export default function addRestoreCommand(app: Application) { groups, }); - await app.restart(); + await app.upgrade(); }); } diff --git a/packages/plugins/@nocobase/plugin-backup-restore/src/server/restorer.ts b/packages/plugins/@nocobase/plugin-backup-restore/src/server/restorer.ts index 33edc04de..c545d3600 100644 --- a/packages/plugins/@nocobase/plugin-backup-restore/src/server/restorer.ts +++ b/packages/plugins/@nocobase/plugin-backup-restore/src/server/restorer.ts @@ -79,7 +79,6 @@ export class Restorer extends AppMigrator { await this.checkMeta(); await this.importCollections(options); await this.importDb(options); - await this.upgradeApp(); await this.clearWorkDir(); } @@ -398,8 +397,4 @@ export class Restorer extends AppMigrator { } } } - - async upgradeApp() { - await this.app.runCommand('upgrade'); - } } From 37b97c6e5209ea3927f60c3aa2b5c69ae0ba7fba Mon Sep 17 00:00:00 2001 From: ChengLei Shao Date: Tue, 12 Mar 2024 14:53:12 +0800 Subject: [PATCH 08/11] chore: escape underscore char in include query (#3681) --- .../operator/string-operator.test.ts | 16 +++++++++++ .../core/database/src/operators/string.ts | 28 +++++++++++-------- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/packages/core/database/src/__tests__/operator/string-operator.test.ts b/packages/core/database/src/__tests__/operator/string-operator.test.ts index d3bc960d7..696d1cba0 100644 --- a/packages/core/database/src/__tests__/operator/string-operator.test.ts +++ b/packages/core/database/src/__tests__/operator/string-operator.test.ts @@ -24,6 +24,22 @@ describe('string operator', () => { }); }); + it('should escape underscore in inlcude operator', async () => { + const u1 = await db.getRepository('users').create({ + values: { + name: 'names of u1', + }, + }); + + const u1Res = await db.getRepository('users').findOne({ + filter: { + 'name.$includes': '_', + }, + }); + + expect(u1Res).toBeNull(); + }); + it('should query with include operator', async () => { const u1 = await db.getRepository('users').create({ values: { diff --git a/packages/core/database/src/operators/string.ts b/packages/core/database/src/operators/string.ts index c87a34b73..4c688ebd6 100644 --- a/packages/core/database/src/operators/string.ts +++ b/packages/core/database/src/operators/string.ts @@ -1,11 +1,15 @@ import { Op } from 'sequelize'; import { isPg } from './utils'; +function escapeLike(value: string) { + return value.replace(/[_%]/g, '\\$&'); +} + export default { $includes(value, ctx) { if (Array.isArray(value)) { const conditions = value.map((item) => ({ - [isPg(ctx) ? Op.iLike : Op.like]: `%${item}%`, + [isPg(ctx) ? Op.iLike : Op.like]: `%${escapeLike(item)}%`, })); return { @@ -14,14 +18,14 @@ export default { } return { - [isPg(ctx) ? Op.iLike : Op.like]: `%${value}%`, + [isPg(ctx) ? Op.iLike : Op.like]: `%${escapeLike(value)}%`, }; }, $notIncludes(value, ctx) { if (Array.isArray(value)) { const conditions = value.map((item) => ({ - [isPg(ctx) ? Op.notILike : Op.notLike]: `%${item}%`, + [isPg(ctx) ? Op.notILike : Op.notLike]: `%${escapeLike(item)}%`, })); return { @@ -30,14 +34,14 @@ export default { } return { - [isPg(ctx) ? Op.notILike : Op.notLike]: `%${value}%`, + [isPg(ctx) ? Op.notILike : Op.notLike]: `%${escapeLike(value)}%`, }; }, $startsWith(value, ctx) { if (Array.isArray(value)) { const conditions = value.map((item) => ({ - [isPg(ctx) ? Op.iLike : Op.like]: `${item}%`, + [isPg(ctx) ? Op.iLike : Op.like]: `${escapeLike(item)}%`, })); return { @@ -46,14 +50,14 @@ export default { } return { - [isPg(ctx) ? Op.iLike : Op.like]: `${value}%`, + [isPg(ctx) ? Op.iLike : Op.like]: `${escapeLike(value)}%`, }; }, $notStartsWith(value, ctx) { if (Array.isArray(value)) { const conditions = value.map((item) => ({ - [isPg(ctx) ? Op.notILike : Op.notLike]: `${item}%`, + [isPg(ctx) ? Op.notILike : Op.notLike]: `${escapeLike(item)}%`, })); return { @@ -62,14 +66,14 @@ export default { } return { - [isPg(ctx) ? Op.notILike : Op.notLike]: `${value}%`, + [isPg(ctx) ? Op.notILike : Op.notLike]: `${escapeLike(value)}%`, }; }, $endWith(value, ctx) { if (Array.isArray(value)) { const conditions = value.map((item) => ({ - [isPg(ctx) ? Op.iLike : Op.like]: `%${item}`, + [isPg(ctx) ? Op.iLike : Op.like]: `%${escapeLike(item)}`, })); return { @@ -78,14 +82,14 @@ export default { } return { - [isPg(ctx) ? Op.iLike : Op.like]: `%${value}`, + [isPg(ctx) ? Op.iLike : Op.like]: `%${escapeLike(value)}`, }; }, $notEndWith(value, ctx) { if (Array.isArray(value)) { const conditions = value.map((item) => ({ - [isPg(ctx) ? Op.notILike : Op.notLike]: `%${item}`, + [isPg(ctx) ? Op.notILike : Op.notLike]: `%${escapeLike(item)}`, })); return { @@ -94,7 +98,7 @@ export default { } return { - [isPg(ctx) ? Op.notILike : Op.notLike]: `%${value}`, + [isPg(ctx) ? Op.notILike : Op.notLike]: `%${escapeLike(value)}`, }; }, } as Record; From de6e8469d3f7e6c2ee244e88863d0414692ec0c3 Mon Sep 17 00:00:00 2001 From: jack zhang <1098626505@qq.com> Date: Tue, 12 Mar 2024 15:13:56 +0800 Subject: [PATCH 09/11] fix: data source add field refresh(T-3253) (#3645) --- .../src/client/component/CollectionsManager/AddFieldAction.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/CollectionsManager/AddFieldAction.tsx b/packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/CollectionsManager/AddFieldAction.tsx index 4a28e0fa6..b1d4c6cb2 100644 --- a/packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/CollectionsManager/AddFieldAction.tsx +++ b/packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/CollectionsManager/AddFieldAction.tsx @@ -22,6 +22,7 @@ import { useCurrentAppInfo, useAPIClient, useFieldInterfaceOptions, + useDataSourceManager, } from '@nocobase/client'; import { ForeignKey } from './components'; @@ -157,6 +158,7 @@ const useCreateCollectionField = () => { const api = useAPIClient(); const record = useRecord(); const { name: dataSourceKey } = useParams(); + const dm = useDataSourceManager(); return { async run() { await form.submit(); @@ -176,6 +178,7 @@ const useCreateCollectionField = () => { data: values, }); ctx.setVisible(false); + dm.getDataSource(dataSourceKey).reload(); await form.reset(); field.data.loading = false; refresh(); From 023096b1a9ea6ccae364c81ba93ca32b077ccecc Mon Sep 17 00:00:00 2001 From: Chareice Date: Tue, 12 Mar 2024 15:14:59 +0800 Subject: [PATCH 10/11] fix: pagination error in roles collections resourcer --- .../roles-data-sources-collections.ts | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/packages/plugins/@nocobase/plugin-data-source-manager/src/server/resourcers/roles-data-sources-collections.ts b/packages/plugins/@nocobase/plugin-data-source-manager/src/server/resourcers/roles-data-sources-collections.ts index fd3d2688d..1eda1661f 100644 --- a/packages/plugins/@nocobase/plugin-data-source-manager/src/server/resourcers/roles-data-sources-collections.ts +++ b/packages/plugins/@nocobase/plugin-data-source-manager/src/server/resourcers/roles-data-sources-collections.ts @@ -22,7 +22,7 @@ const rolesRemoteCollectionsResourcer = { const collectionRepository = new FullDataRepository(dataSource.collectionManager.getCollections()); // all collections - const [collections, count] = await collectionRepository.findAndCount(); + const [collections] = await collectionRepository.findAndCount(); const filterItem = lodash.get(filter, '$and'); const filterByTitle = filterItem?.find((item) => item.title); @@ -45,44 +45,44 @@ const rolesRemoteCollectionsResourcer = { .filter((roleResources) => roleResources.get('usingActionsConfig')) .map((roleResources) => roleResources.get('name')); + const filtedCollections = collections.filter((collection) => { + return ( + (!filterTitle || lodash.get(collection, 'options.title')?.toLowerCase().includes(filterTitle)) && + (!filterName || collection.options.name.toLowerCase().includes(filterName)) + ); + }); + const items = lodash.sortBy( - collections - .filter((collection) => { - return ( - (!filterTitle || lodash.get(collection, 'options.title')?.toLowerCase().includes(filterTitle)) && - (!filterName || collection.options.name.toLowerCase().includes(filterName)) - ); - }) - .map((collection, i) => { - const collectionName = collection.options.name; - const exists = roleResourcesNames.includes(collectionName); + filtedCollections.map((collection, i) => { + const collectionName = collection.options.name; + const exists = roleResourcesNames.includes(collectionName); - const usingConfig: UsingConfigType = roleResourceActionResourceNames.includes(collectionName) - ? 'resourceAction' - : 'strategy'; + const usingConfig: UsingConfigType = roleResourceActionResourceNames.includes(collectionName) + ? 'resourceAction' + : 'strategy'; - return { - type: 'collection', - name: collectionName, - collectionName, - title: collection.options.uiSchema?.title || collection.options.title, - roleName: role, - usingConfig, - exists, - fields: [...collection.fields.values()].map((field) => { - return field.options; - }), - }; - }), + return { + type: 'collection', + name: collectionName, + collectionName, + title: collection.options.uiSchema?.title || collection.options.title, + roleName: role, + usingConfig, + exists, + fields: [...collection.fields.values()].map((field) => { + return field.options; + }), + }; + }), 'name', ); ctx.body = { - count, + count: filtedCollections.length, rows: items, page: Number(page), pageSize: Number(pageSize), - totalPage: totalPage(count, pageSize), + totalPage: totalPage(filtedCollections.length, pageSize), }; await next(); From 559cbca3960caa7a3e06d06b44ae88a0c4d78129 Mon Sep 17 00:00:00 2001 From: katherinehhh Date: Tue, 12 Mar 2024 17:27:35 +0800 Subject: [PATCH 11/11] refactor: add child in inheritance of tree collection (#3676) * refactor: add child in inheritance of tree collection * refactor: add child in inheritance of tree collection * style: style improve --- .../add-child/CreateChildInitializer.tsx | 5 ++-- .../add-child/addChildActionSettings.tsx | 25 +++++++++++++++++-- .../antd/action/Action.Designer.tsx | 4 +-- .../components/CreateRecordAction.tsx | 19 +++++++++++--- 4 files changed, 43 insertions(+), 10 deletions(-) diff --git a/packages/core/client/src/modules/actions/add-child/CreateChildInitializer.tsx b/packages/core/client/src/modules/actions/add-child/CreateChildInitializer.tsx index 58a237a6f..9c82a52b5 100644 --- a/packages/core/client/src/modules/actions/add-child/CreateChildInitializer.tsx +++ b/packages/core/client/src/modules/actions/add-child/CreateChildInitializer.tsx @@ -10,10 +10,11 @@ export const CreateChildInitializer = (props) => { 'x-component': 'Action', 'x-visible': '{{treeTable}}', 'x-component-props': { - icon: 'PlusOutlined', openMode: 'drawer', - type: 'primary', + type: 'link', addChild: true, + style: { padding: '0px', marginTop: '-5px' }, + component: 'CreateRecordAction', }, properties: { drawer: { diff --git a/packages/core/client/src/modules/actions/add-child/addChildActionSettings.tsx b/packages/core/client/src/modules/actions/add-child/addChildActionSettings.tsx index 6bd6ce06c..0298db713 100644 --- a/packages/core/client/src/modules/actions/add-child/addChildActionSettings.tsx +++ b/packages/core/client/src/modules/actions/add-child/addChildActionSettings.tsx @@ -1,9 +1,11 @@ +import { useFieldSchema } from '@formily/react'; +import { useMemo } from 'react'; import { useSchemaToolbar } from '../../../application'; import { SchemaSettings } from '../../../application/schema-settings/SchemaSettings'; -import { useCollection_deprecated } from '../../../collection-manager'; +import { useCollection_deprecated, useCollectionManager_deprecated } from '../../../collection-manager'; import { ButtonEditor } from '../../../schema-component/antd/action/Action.Designer'; import { SchemaSettingOpenModeSchemaItems } from '../../../schema-items'; -import { SchemaSettingsLinkageRules } from '../../../schema-settings'; +import { SchemaSettingsLinkageRules, SchemaSettingsEnableChildCollections } from '../../../schema-settings'; export const addChildActionSettings = new SchemaSettings({ name: 'actionSettings:addChild', @@ -36,6 +38,25 @@ export const addChildActionSettings = new SchemaSettings({ openSize: true, }, }, + { + name: 'enableChildCollections', + Component: SchemaSettingsEnableChildCollections, + useVisible() { + const { name } = useCollection_deprecated(); + const { getChildrenCollections } = useCollectionManager_deprecated(); + const isChildCollectionAction = useMemo( + () => getChildrenCollections(name).length > 0, + [getChildrenCollections, name], + ); + return isChildCollectionAction; + }, + useComponentProps() { + const { name } = useCollection_deprecated(); + return { + collectionName: name, + }; + }, + }, { name: 'delete', type: 'remove', diff --git a/packages/core/client/src/schema-component/antd/action/Action.Designer.tsx b/packages/core/client/src/schema-component/antd/action/Action.Designer.tsx index cdd890d9f..ce184b1ec 100644 --- a/packages/core/client/src/schema-component/antd/action/Action.Designer.tsx +++ b/packages/core/client/src/schema-component/antd/action/Action.Designer.tsx @@ -89,11 +89,11 @@ export function ButtonEditor(props) { field.title = title; field.componentProps.icon = icon; field.componentProps.danger = type === 'danger'; - field.componentProps.type = type; + field.componentProps.type = type || field.componentProps.type; fieldSchema['x-component-props'] = fieldSchema['x-component-props'] || {}; fieldSchema['x-component-props'].icon = icon; fieldSchema['x-component-props'].danger = type === 'danger'; - fieldSchema['x-component-props'].type = type; + fieldSchema['x-component-props'].type = type || field.componentProps.type; dn.emit('patch', { schema: { ['x-uid']: fieldSchema['x-uid'], diff --git a/packages/core/client/src/schema-initializer/components/CreateRecordAction.tsx b/packages/core/client/src/schema-initializer/components/CreateRecordAction.tsx index e072b4dd0..70387ce7c 100644 --- a/packages/core/client/src/schema-initializer/components/CreateRecordAction.tsx +++ b/packages/core/client/src/schema-initializer/components/CreateRecordAction.tsx @@ -292,8 +292,13 @@ function FinallyButton({ type={componentType} icon={} buttonsRender={([leftButton, rightButton]) => [ - leftButton, - React.cloneElement(rightButton as React.ReactElement, { loading: false }), + React.cloneElement(leftButton as React.ReactElement, { + style: props?.style, + }), + React.cloneElement(rightButton as React.ReactElement, { + loading: false, + style: props?.style, + }), ]} menu={menu} onClick={(info) => { @@ -306,7 +311,13 @@ function FinallyButton({ ) : ( { - } @@ -337,9 +348,9 @@ function FinallyButton({ ); } - return (