From af02e80b6fd98e78b5cc2495ac68a73711c48b70 Mon Sep 17 00:00:00 2001 From: Chareice Date: Tue, 8 Feb 2022 16:36:48 +0800 Subject: [PATCH] feat: uiSchema with attributes --- .../src/__tests__/server-hook.test.ts | 77 +++++++++++++++++++ .../src/collections/uiSchemaAttr.ts | 13 ++++ .../src/collections/ui_schemas.ts | 6 ++ .../src/repository.ts | 38 ++++++--- .../plugin-ui-schema-storage/src/server.ts | 6 +- 5 files changed, 128 insertions(+), 12 deletions(-) create mode 100644 packages/plugin-ui-schema-storage/src/__tests__/server-hook.test.ts create mode 100644 packages/plugin-ui-schema-storage/src/collections/uiSchemaAttr.ts diff --git a/packages/plugin-ui-schema-storage/src/__tests__/server-hook.test.ts b/packages/plugin-ui-schema-storage/src/__tests__/server-hook.test.ts new file mode 100644 index 000000000..c4d745879 --- /dev/null +++ b/packages/plugin-ui-schema-storage/src/__tests__/server-hook.test.ts @@ -0,0 +1,77 @@ +import { mockServer, MockServer } from '@nocobase/test'; +import { Database } from '@nocobase/database'; +import PluginUiSchema, { UiSchemaRepository } from '@nocobase/plugin-ui-schema-storage'; + +describe('server hooks', () => { + let app: MockServer; + let db: Database; + let uiSchemaRepository: UiSchemaRepository; + + afterEach(async () => { + await app.destroy(); + }); + + beforeEach(async () => { + app = mockServer({ + registerActions: true, + }); + + db = app.db; + + await app.cleanDb(); + app.plugin(PluginUiSchema); + + await app.loadAndInstall(); + + uiSchemaRepository = db.getRepository('ui_schemas'); + }); + + it('should save uiSchemaAttrs', async () => { + const schema = { + name: 'row', + 'x-uid': 'table', + 'x-component': 'Table', + 'x-collection': 'posts', + 'x-server-hooks': { + afterDestroyCollection: ['aaa'], + }, + properties: { + col1: { + 'x-uid': 'col1', + 'x-component': 'Col', + properties: { + field1: { + 'x-uid': 'field1', + 'x-component': 'Input', + 'x-collection-field': 'posts.title', + 'x-server-hooks': { + afterDestroyField: ['bbb'], + }, + }, + }, + }, + }, + }; + + await uiSchemaRepository.insert(schema); + const node = await uiSchemaRepository.findOne({ + filter: { + uid: 'table', + }, + }); + + // @ts-ignore + const nodeAttr = await node.getAttrs(); + expect(nodeAttr.get('collectionPath')).toEqual('posts'); + + const nodeField = await uiSchemaRepository.findOne({ + filter: { + uid: 'field1', + }, + }); + + // @ts-ignore + const nodeFieldAttr = await nodeField.getAttrs(); + expect(nodeFieldAttr.get('collectionPath')).toEqual('posts.title'); + }); +}); diff --git a/packages/plugin-ui-schema-storage/src/collections/uiSchemaAttr.ts b/packages/plugin-ui-schema-storage/src/collections/uiSchemaAttr.ts new file mode 100644 index 000000000..3445f9ed1 --- /dev/null +++ b/packages/plugin-ui-schema-storage/src/collections/uiSchemaAttr.ts @@ -0,0 +1,13 @@ +import { CollectionOptions } from '@nocobase/database'; + +export default { + name: 'uiSchemaAttrs', + autoGenId: false, + timestamps: false, + fields: [ + { + type: 'string', + name: 'collectionPath', + }, + ], +} as CollectionOptions; diff --git a/packages/plugin-ui-schema-storage/src/collections/ui_schemas.ts b/packages/plugin-ui-schema-storage/src/collections/ui_schemas.ts index 6e05213a4..76f1eece6 100644 --- a/packages/plugin-ui-schema-storage/src/collections/ui_schemas.ts +++ b/packages/plugin-ui-schema-storage/src/collections/ui_schemas.ts @@ -25,6 +25,12 @@ export default { type: 'string', name: 'name', }, + { + type: 'hasOne', + name: 'attrs', + target: 'uiSchemaAttrs', + foreignKey: 'uid', + }, { type: 'json', name: 'schema', diff --git a/packages/plugin-ui-schema-storage/src/repository.ts b/packages/plugin-ui-schema-storage/src/repository.ts index 8d350221d..c6c8b8d4e 100644 --- a/packages/plugin-ui-schema-storage/src/repository.ts +++ b/packages/plugin-ui-schema-storage/src/repository.ts @@ -385,6 +385,34 @@ export default class UiSchemaRepository extends Repository { }); } + private async insertSchemaRecord(name, uid, schema, transaction) { + const node = await this.create({ + values: { + name, + uid, + schema, + }, + transaction, + hooks: false, + }); + + await this.insertSchemaAttrs(node, transaction); + return node; + } + + private async insertSchemaAttrs(schema, transaction) { + const collectionPath = schema.get('x-collection') || schema.get('x-collection-field'); + + if (collectionPath) { + await this.database.getRepository('uiSchemaAttrs').create({ + values: { + uid: schema.get('uid'), + collectionPath: collectionPath, + }, + }); + } + } + async insertSingleNode(schema: SchemaNode, transaction: Transaction) { const db = this.database; const treeCollection = db.getCollection('ui_schema_tree_path'); @@ -414,15 +442,7 @@ export default class UiSchemaRepository extends Repository { if (existsNode) { savedNode = existsNode; } else { - savedNode = await this.create({ - values: { - name, - uid, - schema, - }, - transaction, - hooks: false, - }); + savedNode = await this.insertSchemaRecord(name, uid, schema, transaction); } if (childOptions) { diff --git a/packages/plugin-ui-schema-storage/src/server.ts b/packages/plugin-ui-schema-storage/src/server.ts index 306d5566b..b967e18e7 100644 --- a/packages/plugin-ui-schema-storage/src/server.ts +++ b/packages/plugin-ui-schema-storage/src/server.ts @@ -18,11 +18,11 @@ export default class PluginUiSchema extends Plugin { this.registerRepository(); - db.on('ui_schemas.beforeCreate', (model) => { + db.on('ui_schemas.beforeCreate', function setUid(model) { model.set('uid', model.get('x-uid')); }); - db.on('ui_schemas.afterCreate', async (model, options) => { + db.on('ui_schemas.afterCreate', async function insertSchema(model, options) { const { transaction } = options; const uiSchemaRepository = db.getCollection('ui_schemas').repository as UiSchemaRepository; @@ -31,7 +31,7 @@ export default class PluginUiSchema extends Plugin { }); }); - db.on('ui_schemas.afterUpdate', async (model, options) => { + db.on('ui_schemas.afterUpdate', async function patchSchema(model, options) { const { transaction } = options; const uiSchemaRepository = db.getCollection('ui_schemas').repository as UiSchemaRepository;