From a0aa3b8663fe74c41a268cf8a3e91131a5f4a8af Mon Sep 17 00:00:00 2001 From: YANG QIA <2013xile@gmail.com> Date: Sat, 7 Dec 2024 21:28:20 +0800 Subject: [PATCH] fix(m2m-array): issue where updating m2m array fields in single relation collection (#5820) * fix(m2m-array): issue where updating m2m array fields in single relation collection * fix: select * test: add test cases --- .../antd/association-field/FileManager.tsx | 2 +- .../single-relation-repository.ts | 2 +- .../src/server/__tests__/issues.test.ts | 104 ++++++++++++++++++ .../__tests__/m2m-array-bigint-api.test.ts | 12 ++ .../__tests__/m2m-array-string-api.test.ts | 8 ++ .../src/server/belongs-to-array-field.ts | 5 +- 6 files changed, 130 insertions(+), 3 deletions(-) diff --git a/packages/core/client/src/schema-component/antd/association-field/FileManager.tsx b/packages/core/client/src/schema-component/antd/association-field/FileManager.tsx index 73c9d3dc4c..05c778d18b 100644 --- a/packages/core/client/src/schema-component/antd/association-field/FileManager.tsx +++ b/packages/core/client/src/schema-component/antd/association-field/FileManager.tsx @@ -195,7 +195,7 @@ const InternalFileManager = (props) => { const pickerProps = { size: 'small', fieldNames, - multiple: ['o2m', 'm2m'].includes(collectionField?.interface) && multiple, + multiple: ['o2m', 'm2m', 'mbm'].includes(collectionField?.interface) && multiple, association: { target: collectionField?.target, }, diff --git a/packages/core/database/src/relation-repository/single-relation-repository.ts b/packages/core/database/src/relation-repository/single-relation-repository.ts index a204b0cbc3..02f9c16004 100644 --- a/packages/core/database/src/relation-repository/single-relation-repository.ts +++ b/packages/core/database/src/relation-repository/single-relation-repository.ts @@ -108,7 +108,7 @@ export abstract class SingleRelationRepository extends RelationRepository { } await updateModelByValues(target, options?.values, { - ...lodash.omit(options, 'values'), + ...options, transaction, }); diff --git a/packages/plugins/@nocobase/plugin-field-m2m-array/src/server/__tests__/issues.test.ts b/packages/plugins/@nocobase/plugin-field-m2m-array/src/server/__tests__/issues.test.ts index 36220b55a7..af33944c43 100644 --- a/packages/plugins/@nocobase/plugin-field-m2m-array/src/server/__tests__/issues.test.ts +++ b/packages/plugins/@nocobase/plugin-field-m2m-array/src/server/__tests__/issues.test.ts @@ -112,4 +112,108 @@ describe('m2m array api, bigInt targetKey', () => { }); expect(res.status).toBe(200); }); + + test('update m2m array field in single realtion collection', async () => { + await db.getRepository('collections').create({ + values: { + name: 'tags', + fields: [ + { + name: 'id', + type: 'bigInt', + autoIncrement: true, + primaryKey: true, + allowNull: false, + }, + { + name: 'title', + type: 'string', + }, + ], + }, + }); + await db.getRepository('collections').create({ + values: { + name: 'users', + fields: [ + { + name: 'id', + type: 'bigInt', + autoIncrement: true, + primaryKey: true, + allowNull: false, + }, + { + name: 'username', + type: 'string', + }, + { + name: 'tags', + type: 'belongsToArray', + foreignKey: 'tag_ids', + target: 'tags', + targetKey: 'id', + }, + ], + }, + }); + await db.getRepository('collections').create({ + values: { + name: 'projects', + fields: [ + { + name: 'id', + type: 'bigInt', + autoIncrement: true, + primaryKey: true, + allowNull: false, + }, + { + name: 'title', + type: 'string', + }, + { + name: 'users', + type: 'belongsTo', + foreignKey: 'user_id', + target: 'users', + }, + ], + }, + }); + // @ts-ignore + await db.getRepository('collections').load(); + await db.sync(); + await db.getRepository('tags').create({ + values: [{ title: 'a' }, { title: 'b' }, { title: 'c' }], + }); + await db.getRepository('users').create({ + values: { id: 1, username: 'a' }, + }); + let user = await db.getRepository('users').findOne({ + filterByTk: 1, + }); + expect(user.tag_ids).toEqual(null); + await db.getRepository('projects').create({ + values: { id: 1, title: 'p1', user_id: 1 }, + }); + const res = await agent.resource('projects.users', 1).update({ + filterByTk: 1, + values: { + tags: [ + { id: 1, title: 'a' }, + { id: 2, title: 'b' }, + ], + }, + }); + user = await db.getRepository('users').findOne({ + filterByTk: 1, + }); + if (db.sequelize.getDialect() === 'postgres') { + expect(user.tag_ids).toMatchObject(['1', '2']); + } else { + expect(user.tag_ids).toMatchObject([1, 2]); + } + expect(res.status).toBe(200); + }); }); diff --git a/packages/plugins/@nocobase/plugin-field-m2m-array/src/server/__tests__/m2m-array-bigint-api.test.ts b/packages/plugins/@nocobase/plugin-field-m2m-array/src/server/__tests__/m2m-array-bigint-api.test.ts index 5eef17ccda..d14c755277 100644 --- a/packages/plugins/@nocobase/plugin-field-m2m-array/src/server/__tests__/m2m-array-bigint-api.test.ts +++ b/packages/plugins/@nocobase/plugin-field-m2m-array/src/server/__tests__/m2m-array-bigint-api.test.ts @@ -256,6 +256,18 @@ describe('m2m array api, bigInt targetKey', () => { } else { expect(user2.tag_ids).toMatchObject([1, 3]); } + const user3 = await db.getRepository('users').create({ + values: { + id: 5, + username: 'e', + tags: { id: 1 }, + }, + }); + if (db.sequelize.getDialect() === 'postgres') { + expect(user3.tag_ids).toMatchObject(['1']); + } else { + expect(user3.tag_ids).toMatchObject([1]); + } }); it('should create target when creating belongsToArray', async () => { diff --git a/packages/plugins/@nocobase/plugin-field-m2m-array/src/server/__tests__/m2m-array-string-api.test.ts b/packages/plugins/@nocobase/plugin-field-m2m-array/src/server/__tests__/m2m-array-string-api.test.ts index 76e4cc79d0..bcb3468c01 100644 --- a/packages/plugins/@nocobase/plugin-field-m2m-array/src/server/__tests__/m2m-array-string-api.test.ts +++ b/packages/plugins/@nocobase/plugin-field-m2m-array/src/server/__tests__/m2m-array-string-api.test.ts @@ -227,6 +227,14 @@ describe('m2m array api, string targetKey', () => { }, }); expect(user2.tag_ids).toMatchObject(['a', 'c']); + const user3 = await db.getRepository('users').create({ + values: { + id: 5, + username: 'e', + tags: { stringCode: 'a' }, + }, + }); + expect(user3.tag_ids).toMatchObject(['a']); }); it('should create target when creating belongsToArray', async () => { diff --git a/packages/plugins/@nocobase/plugin-field-m2m-array/src/server/belongs-to-array-field.ts b/packages/plugins/@nocobase/plugin-field-m2m-array/src/server/belongs-to-array-field.ts index 6b4b30ccad..8bf7c1d2fe 100644 --- a/packages/plugins/@nocobase/plugin-field-m2m-array/src/server/belongs-to-array-field.ts +++ b/packages/plugins/@nocobase/plugin-field-m2m-array/src/server/belongs-to-array-field.ts @@ -25,7 +25,10 @@ export class BelongsToArrayField extends RelationField { if (!values || values[name] === undefined) { return; } - const value: any[] = values[name] || []; + let value: any[] = values[name] || []; + if (!Array.isArray(value)) { + value = [value]; + } const tks = []; const items = []; for (const item of value) {