feat: removeEmptyParents server hook
This commit is contained in:
parent
85ab936c4c
commit
4607e0da49
@ -0,0 +1,160 @@
|
|||||||
|
import { mockServer, MockServer } from '@nocobase/test';
|
||||||
|
import { Database } from '@nocobase/database';
|
||||||
|
import PluginUiSchema, { UiSchemaRepository } from '@nocobase/plugin-ui-schema-storage';
|
||||||
|
import PluginCollectionManager from '@nocobase/plugin-collection-manager';
|
||||||
|
import { removeEmptyParents } from '../server-hooks/removeEmptyParents';
|
||||||
|
|
||||||
|
describe('server hooks', () => {
|
||||||
|
let app: MockServer;
|
||||||
|
let db: Database;
|
||||||
|
let uiSchemaRepository: UiSchemaRepository;
|
||||||
|
let uiSchemaPlugin: PluginUiSchema;
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await app.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
app = mockServer({
|
||||||
|
registerActions: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
db = app.db;
|
||||||
|
|
||||||
|
await app.cleanDb();
|
||||||
|
app.plugin(PluginUiSchema);
|
||||||
|
app.plugin(PluginCollectionManager);
|
||||||
|
|
||||||
|
await app.loadAndInstall();
|
||||||
|
|
||||||
|
uiSchemaRepository = db.getRepository('ui_schemas');
|
||||||
|
|
||||||
|
uiSchemaPlugin = app.getPlugin<PluginUiSchema>('PluginUiSchema');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should clean row struct', async () => {
|
||||||
|
const PostModel = await db.getRepository('collections').create({
|
||||||
|
values: {
|
||||||
|
name: 'posts',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await db.getRepository('fields').create({
|
||||||
|
values: {
|
||||||
|
name: 'title',
|
||||||
|
type: 'string',
|
||||||
|
collectionName: 'posts',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await db.getRepository('fields').create({
|
||||||
|
values: {
|
||||||
|
name: 'name',
|
||||||
|
type: 'string',
|
||||||
|
collectionName: 'posts',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await db.getRepository('fields').create({
|
||||||
|
values: {
|
||||||
|
name: 'intro',
|
||||||
|
type: 'string',
|
||||||
|
collectionName: 'posts',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const schema = {
|
||||||
|
type: 'void',
|
||||||
|
name: 'grid1',
|
||||||
|
'x-decorator': 'Form',
|
||||||
|
'x-component': 'Grid',
|
||||||
|
'x-item-initializer': 'AddGridFormItem',
|
||||||
|
'x-uid': 'grid1',
|
||||||
|
properties: {
|
||||||
|
row1: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Grid.Row',
|
||||||
|
'x-uid': 'row1',
|
||||||
|
properties: {
|
||||||
|
col11: {
|
||||||
|
type: 'void',
|
||||||
|
'x-uid': 'col11',
|
||||||
|
'x-component': 'Grid.Col',
|
||||||
|
properties: {
|
||||||
|
name: {
|
||||||
|
type: 'string',
|
||||||
|
title: 'Name',
|
||||||
|
'x-uid': 'posts-name',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-component': 'Input',
|
||||||
|
'x-collection-field': 'posts.name',
|
||||||
|
'x-server-hooks': [
|
||||||
|
{
|
||||||
|
type: 'onCollectionFieldDestroy',
|
||||||
|
collection: 'posts',
|
||||||
|
fields: ['name'],
|
||||||
|
method: 'removeEmptyParents',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: 'string',
|
||||||
|
title: 'Title',
|
||||||
|
'x-uid': 'posts-title',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-component': 'Input',
|
||||||
|
'x-collection-field': 'posts.title',
|
||||||
|
'x-server-hooks': [
|
||||||
|
{
|
||||||
|
type: 'onCollectionFieldDestroy',
|
||||||
|
collection: 'posts',
|
||||||
|
fields: ['title'],
|
||||||
|
method: 'removeEmptyParents',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
col12: {
|
||||||
|
type: 'void',
|
||||||
|
'x-uid': 'col12',
|
||||||
|
'x-component': 'Grid.Col',
|
||||||
|
properties: {
|
||||||
|
intro: {
|
||||||
|
'x-uid': 'posts-intro',
|
||||||
|
type: 'string',
|
||||||
|
title: 'Intro',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-component': 'Input',
|
||||||
|
'x-server-hooks': [
|
||||||
|
{
|
||||||
|
type: 'onCollectionFieldDestroy',
|
||||||
|
collection: 'posts',
|
||||||
|
fields: ['intro'],
|
||||||
|
method: 'removeEmptyParents',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
await uiSchemaRepository.insert(schema);
|
||||||
|
|
||||||
|
uiSchemaPlugin.serverHooks.register('onCollectionFieldDestroy', 'removeEmptyParents', removeEmptyParents);
|
||||||
|
|
||||||
|
await db.getRepository('fields').destroy({
|
||||||
|
filter: {
|
||||||
|
name: 'intro',
|
||||||
|
},
|
||||||
|
individualHooks: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const jsonTree = await uiSchemaRepository.getJsonSchema('grid1');
|
||||||
|
expect(jsonTree['properties']['row1']['properties']['col11']).toBeDefined();
|
||||||
|
expect(jsonTree['properties']['row1']['properties']['col12']).not.toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
@ -178,11 +178,7 @@ describe('server hooks', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
await uiSchemaRepository.create({
|
await uiSchemaRepository.insert(menuSchema);
|
||||||
values: {
|
|
||||||
schema: menuSchema,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const PostModel = await db.getRepository('collections').create({
|
const PostModel = await db.getRepository('collections').create({
|
||||||
values: {
|
values: {
|
||||||
|
@ -110,7 +110,7 @@ export class ServerHooks {
|
|||||||
const hookFunc = this.hooks.get(hookRecord.get('type') as HookType)?.get(hoodMethodName);
|
const hookFunc = this.hooks.get(hookRecord.get('type') as HookType)?.get(hoodMethodName);
|
||||||
|
|
||||||
if (hookFunc) {
|
if (hookFunc) {
|
||||||
await hookFunc({ ...hooksArgs, schemaInstance: (<any>hookRecord).uiSchema });
|
await hookFunc({ ...hooksArgs, schemaInstance: (<any>hookRecord).uiSchema, db: this.db });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,52 @@
|
|||||||
|
import { UiSchemaRepository } from '@nocobase/plugin-ui-schema-storage';
|
||||||
|
|
||||||
|
// given a child uid, if it is a single child ,return its parent
|
||||||
|
async function isSingleChild(uid, db, transaction) {
|
||||||
|
const parent = await db.getRepository('ui_schema_tree_path').findOne({
|
||||||
|
filter: {
|
||||||
|
descendant: uid,
|
||||||
|
depth: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const countResult = await db.sequelize.query(
|
||||||
|
`SELECT COUNT(*) FROM ${
|
||||||
|
db.getCollection('ui_schema_tree_path').model.tableName
|
||||||
|
} where ancestor = :ancestor and depth = 1`,
|
||||||
|
{
|
||||||
|
replacements: {
|
||||||
|
ancestor: parent.get('ancestor'),
|
||||||
|
},
|
||||||
|
type: 'SELECT',
|
||||||
|
transaction,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const parentChildrenCount = countResult[0]['count'];
|
||||||
|
|
||||||
|
if (parentChildrenCount == 1) {
|
||||||
|
return parent.get('ancestor');
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function removeEmptyParents({ schemaInstance, options, db }) {
|
||||||
|
const { transaction } = options;
|
||||||
|
const uiSchemaRepository: UiSchemaRepository = db.getRepository('ui_schemas');
|
||||||
|
const uid = schemaInstance.get('uid');
|
||||||
|
|
||||||
|
// find parent uid
|
||||||
|
const parentUid = await isSingleChild(uid, db, transaction);
|
||||||
|
|
||||||
|
if (parentUid) {
|
||||||
|
const rowUid = await isSingleChild(parentUid, db, transaction);
|
||||||
|
if (rowUid) {
|
||||||
|
await uiSchemaRepository.remove(rowUid, { transaction });
|
||||||
|
} else {
|
||||||
|
await uiSchemaRepository.remove(parentUid, { transaction });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await uiSchemaRepository.remove(uid, { transaction });
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user