Merge branch 'main' into next

This commit is contained in:
nocobase[bot] 2024-10-28 02:20:05 +00:00
commit 75adb3f865
2 changed files with 102 additions and 37 deletions

View File

@ -570,4 +570,46 @@ describe('tree path test', () => {
// await treeCollection.removeFromDb();
// expect(await db.getCollection(name).existsInDb()).toBeFalsy();
// })
it('should update paths when remove children', async () => {
const data = await treeCollection.repository.create({
values: {
name: 'a1',
children: [
{
name: 'b1',
},
{
name: 'b2',
},
],
},
});
const b1 = data.get('children')[0];
const b2 = data.get('children')[1];
const tks = [b1.get(treeCollection.filterTargetKey), b2.get(treeCollection.filterTargetKey)];
const paths = await db.getRepository(name).find({
filter: {
[nodePkColumnName]: {
$in: tks,
},
},
});
expect(paths.length).toBe(2);
expect(paths[0].get('path')).toBe('/1/2');
expect(paths[1].get('path')).toBe('/1/3');
// @ts-ignore
await db.getRepository(`${treeCollection.name}.children`, data.get(treeCollection.filterTargetKey)).remove(tks);
const paths2 = await db.getRepository(name).find({
filter: {
[nodePkColumnName]: {
$in: tks,
},
},
});
console.log(paths2);
expect(paths2.length).toBe(2);
expect(paths2[0].get('path')).toBe('/2');
expect(paths2[1].get('path')).toBe('/3');
});
});

View File

@ -14,11 +14,6 @@ import lodash from 'lodash';
import { Transaction } from 'sequelize';
import { TreeCollection } from './tree-collection';
const getFilterTargetKey = (model: Model) => {
// @ts-ignore
return model.constructor.collection.filterTargetKey;
};
class PluginCollectionTreeServer extends Plugin {
async beforeLoad() {
const condition = (options) => {
@ -55,7 +50,7 @@ class PluginCollectionTreeServer extends Plugin {
//afterCreate
this.db.on(`${collection.name}.afterCreate`, async (model: Model, options) => {
const { transaction } = options;
const tk = getFilterTargetKey(model);
const tk = collection.filterTargetKey;
let path = `/${model.get(tk)}`;
path = await this.getTreePath(model, path, collection, name, transaction);
const rootPk = path.split('/')[1];
@ -71,49 +66,35 @@ class PluginCollectionTreeServer extends Plugin {
//afterUpdate
this.db.on(`${collection.name}.afterUpdate`, async (model: Model, options) => {
const tk = getFilterTargetKey(model);
const tk = collection.filterTargetKey;
// only update parentId and filterTargetKey
if (!(model._changed.has(tk) || model._changed.has(parentForeignKey))) {
return;
}
const { transaction } = options;
let path = `/${model.get(tk)}`;
path = await this.getTreePath(model, path, collection, name, transaction);
const collectionTreePath = this.db.getCollection(name);
const nodePkColumnName = collectionTreePath.getField('nodePk').columnName();
const pathData = await this.app.db.getRepository(name).findOne({
filter: {
[nodePkColumnName]: model.get(tk),
},
transaction,
});
await this.updateTreePath(model, collection, name, transaction);
});
const relatedNodes = await this.app.db.getRepository(name).find({
filter: {
path: {
$startsWith: `${pathData.get('path')}`,
},
// after remove
this.db.on(`${collection.name}.afterBulkUpdate`, async (options) => {
const tk = collection.filterTargetKey;
if (!(options.where && options.where[tk])) {
return;
}
const instances = await this.db.getRepository(collection.name).find({
where: {
[tk]: options.where[tk],
},
transaction,
transaction: options.transaction,
});
const rootPk = path.split('/')[1];
for (const node of relatedNodes) {
await this.app.db.getRepository(name).update({
values: {
path: node.get('path').replace(`${pathData.get('path')}`, path),
rootPk: rootPk ? Number(rootPk) : null,
},
filter: {
[nodePkColumnName]: node.get('nodePk'),
},
transaction,
});
for (const model of instances) {
await this.updateTreePath(model, collection, name, options.transaction);
}
});
//afterDestroy
this.db.on(`${collection.name}.afterDestroy`, async (model: Model, options: DestroyOptions) => {
const tk = getFilterTargetKey(model);
const tk = collection.filterTargetKey;
await this.app.db.getRepository(name).destroy({
filter: {
nodePk: model.get(tk),
@ -164,7 +145,7 @@ class PluginCollectionTreeServer extends Plugin {
pathCollectionName: string,
transaction?: Transaction,
) {
const tk = getFilterTargetKey(model);
const tk = collection.filterTargetKey;
const parentForeignKey = collection.treeParentField?.foreignKey || 'parentId';
if (model.get(parentForeignKey) && model.get(parentForeignKey) !== null) {
const parent = await this.app.db.getRepository(collection.name).findOne({
@ -195,6 +176,48 @@ class PluginCollectionTreeServer extends Plugin {
}
return path;
}
private async updateTreePath(
model: Model,
collection: Collection,
pathCollectionName: string,
transaction: Transaction,
) {
const tk = collection.filterTargetKey;
let path = `/${model.get(tk)}`;
path = await this.getTreePath(model, path, collection, pathCollectionName, transaction);
const collectionTreePath = this.db.getCollection(pathCollectionName);
const nodePkColumnName = collectionTreePath.getField('nodePk').columnName();
const pathData = await this.app.db.getRepository(pathCollectionName).findOne({
filter: {
[nodePkColumnName]: model.get(tk),
},
transaction,
});
const relatedNodes = await this.app.db.getRepository(pathCollectionName).find({
filter: {
path: {
$startsWith: `${pathData.get('path')}`,
},
},
transaction,
});
const rootPk = path.split('/')[1];
for (const node of relatedNodes) {
const newPath = node.get('path').replace(pathData.get('path'), path);
await this.app.db.getRepository(pathCollectionName).update({
values: {
path: newPath,
rootPk: rootPk ? Number(rootPk) : null,
},
filter: {
[nodePkColumnName]: node.get('nodePk'),
},
transaction,
});
}
}
}
export default PluginCollectionTreeServer;