mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-05 13:39:24 +08:00
* feat: 图形化管理数据表 * feat: 图形化管理数据表 * feat: 图形化管理数据表 * feat: 图形化管理数据表 * feat: 完善图形化管理数据表 * feat: 完善图形化管理数据表 * feat: 完善图形化管理数据表 * feat: 完善图形化管理数据表 * feat: 完善图形化管理数据表 * feat: 完善图形化管理数据表 * feat: 完善图形化管理数据表 * feat: 完善图形化管理数据表 * feat: 完善图形化管理数据表 * feat: 完善图形化管理数据表 * feat: 完善图形化管理数据表 * feat: 完善图形化管理数据表 * feat: 完善图形化管理数据表 * feat: 完善图形化管理数据表 * feat: 完善图形化管理数据表 * feat: 完善图形化管理数据表 * feat: 完善图形化管理数据表 * feat: 样式优化图形化管理数据表 * feat: 样式优化图形化管理数据表 * feat: 样式优化图形化管理数据表 * feat: 样式优化图形化管理数据表 * feat: 样式优化图形化管理数据表 * feat: 样式优化图形化管理数据表 * feat: 样式优化图形化管理数据表 * feat: 样式优化图形化管理数据表 * feat: 样式优化图形化管理数据表 * feat: 样式优化图形化管理数据表 * feat: 样式优化图形化管理数据表 * feat: 样式优化图形化管理数据表 * feat: 样式优化图形化管理数据表 * feat: 样式优化图形化管理数据表 * feat: 样式优化图形化管理数据表 * feat: 样式优化图形化管理数据表 * feat: 样式优化图形化管理数据表 * feat: 样式优化图形化管理数据表 * feat: 样式优化图形化管理数据表 * feat: 样式优化图形化管理数据表 * feat: 样式优化图形化管理数据表 * feat(collection-manager): add foreignKey Field and support relate field record foreignKey info through collection record into collections and foreignKey field record info fields * fix(collection-manager): if has through collection then don't create through collections record * fix(client/route-switch): skip sub routes * feat: 添加graphpostion * feat: 图形化collection新增表时刷新数据 * fix(collection-manager): refactor afterCreateForRelateField * feat: 图形化collection存储位置 * feat: 图形化collection存储位置 * feat: 图形化collection存储位置 * feat: 图形化collection存储位置 * feat: 图形化collection存储位置 * feat: 图形化collection存储位置 * feat: 图形化collection存储位置 * feat: 图形化collection存储位置 * feat: 图形化collection存储位置 * feat: 图形化collection存储位置 * feat: 图形化样式优化 * feat: styling * feat: 图形化样式优化 * feat: 图形化样式优化 * feat: 图形化数据表多语言完善 * feat: 图形化数据表多语言完善 * feat: improve code * feat: 图形化数据表连线样式修改 * feat: 图形化数据表样式修改 * feat: 图形化数据表样式修改 * feat: 图形化数据表样式修改 * feat: 图形化数据表样式修改 * fix(collection-manager): fix afterCreateForRelateField * feat: 样式优化 * feat: 样式优化 * feat: afterCreateForForeignKeyField * fix: timestamps: false * feat: 连线锚点优化 * fix(collection-manager): when del foreign key field, relate fields will be del too * fix: update package.json * fix: update package.json * feat: 文件名大小写 * feat: 连线锚点优化 * feat: 连线锚点通过计算得到样式优化 * feat: 连线锚点通过计算得到样式优化 * fix: fk * fix: remove index * feat: 连线hover时高亮 * fix: test error * feat: 初始化计算位置 * feat: 初始化时计算坐标位置 * feat: 初始化时计算坐标位置 * feat: improve code (#933) * fix: built in * feat: 没有关系字段时也要连线 * feat: 自关联也要连线 * fix: styling * feat: 滚动条问题 * feat: 拖拽优化 * feat: 画布paddig优化 * feat: 编辑时支持反向关联字段配置 * feat: 画布拖拽滚动优化 * feat: 画布拖拽滚动优化 * fix: reload * feat: 修复数据表新建重叠 * fix: refreshCM & refreshGM * feat: 修复表达式输入框显示异常 * feat: 渲染性能优化(增量渲染) * feat: 渲染性能优化(增量渲染) * feat: 渲染性能优化(增量渲染) * fix: 消除代码警告 * fix: 消除代码警告 * feat: 渲染性能优化(增量渲染) * feat: 渲染性能优化(增量渲染) * feat: 渲染性能优化(增量渲染) * feat: 渲染性能优化(增量渲染) * feat: 渲染性能优化(增量渲染) * feat: 渲染性能优化(增量渲染) * feat: 渲染性能优化(增量渲染) * feat: 渲染性能优化 * feat: 渲染性能优化 * feat: 外键生成在位置在前面 * feat: 限制表最多显示10个字段其余滚动 * feat: 移动表位置的连线重新计算最优位置 * fix: error * feat: 布局自动换行 * fix: test error * fix: xpipe.eq * fix: upgrade error * fix: upgrade error * feat: 选中表时只显示和目标表关联的表和连线 * feat: 连线优化 * fix: maxListenersExceededWarning * feat: 连线优化 * feat: powerby样式优化 * feat: 表筛选优化 * feat: 新建字段优化 * feat: 点击线高亮主外键和关联字段 * feat: 点击线高亮主外键和关联字段 * feat: 鼠标hover连线高亮主外键和关联字段 * fix(collection-manager): foreign key sorting should follow ID * fix(client/config-relation-field): set Relation field's ReverseField default value is false * feat: 卡片默认显示主外键和关联字段其余通过折叠展示且分组区分显示 * fix(client/collection-manager): don't display auto create through collections and foreign key only display in graph menu * feat: 样式优化 * feat: 添加字段时默认展开折叠 * feat: 样式优化 * feat: foreign field migration (#1001) * feat: 补充多语言 * feat: settings center tabs * feat: 主键判断primaryKey * fix(collection-manager): foreign key sorting should follow primaryKey * fix(client/block-select-collection): filter auto create through collections * fix(client/block-config-fields): filter isForeignKey fields * fix(client/configuration-table): relation fileds select collection filter auto create through * feat: 多对多连线高亮时全亮 * feat: 选中多对多中的一张表另一张表也显示 * feat: 连线mouseleave事件 * feat: 多语言更新 * feat: 计算新建表位置优化 * feat: 添加自动布局 * feat(client/configure-fields): categorize fields * fix(client/configure-fields): display foreign key fields * fix(client): package reference * fix: remove graph * fix: remove Co-authored-by: 唐小爱 <tangxiaoai@192.168.0.103> Co-authored-by: lyf-coder <lyf-coder@foxmail.com> Co-authored-by: katherinehhh <katherine_15995@163.com> Co-authored-by: ChengLei Shao <chareice@live.com> Co-authored-by: mytharcher <mytharcher@gmail.com>
171 lines
5.1 KiB
TypeScript
171 lines
5.1 KiB
TypeScript
import path from 'path';
|
|
|
|
import lodash from 'lodash';
|
|
import { UniqueConstraintError } from 'sequelize';
|
|
|
|
import PluginErrorHandler from '@nocobase/plugin-error-handler';
|
|
import { Plugin } from '@nocobase/server';
|
|
|
|
import { CollectionRepository } from '.';
|
|
import {
|
|
afterCreateForForeignKeyField,
|
|
afterCreateForReverseField,
|
|
beforeCreateForChildrenCollection,
|
|
beforeCreateForReverseField,
|
|
beforeDestroyForeignKey,
|
|
beforeInitOptions,
|
|
} from './hooks';
|
|
|
|
import { CollectionModel, FieldModel } from './models';
|
|
|
|
export class CollectionManagerPlugin extends Plugin {
|
|
async beforeLoad() {
|
|
this.app.db.registerModels({
|
|
CollectionModel,
|
|
FieldModel,
|
|
});
|
|
|
|
this.db.addMigrations({
|
|
namespace: 'collection-manager',
|
|
directory: path.resolve(__dirname, './migrations'),
|
|
context: {
|
|
plugin: this,
|
|
},
|
|
});
|
|
|
|
this.app.db.registerRepositories({
|
|
CollectionRepository,
|
|
});
|
|
|
|
this.app.db.on('fields.beforeUpdate', async (model, options) => {
|
|
const newValue = options.values;
|
|
if (
|
|
model.get('reverseKey') &&
|
|
lodash.get(newValue, 'reverseField') &&
|
|
!lodash.get(newValue, 'reverseField.key')
|
|
) {
|
|
const field = await this.app.db
|
|
.getModel('fields')
|
|
.findByPk(model.get('reverseKey'), { transaction: options.transaction });
|
|
if (field) {
|
|
throw new Error('cant update field without a reverseField key');
|
|
}
|
|
}
|
|
});
|
|
|
|
// 要在 beforeInitOptions 之前处理
|
|
this.app.db.on('fields.beforeCreate', beforeCreateForReverseField(this.app.db));
|
|
this.app.db.on('fields.beforeCreate', beforeCreateForChildrenCollection(this.app.db));
|
|
this.app.db.on('fields.beforeCreate', async (model, options) => {
|
|
const type = model.get('type');
|
|
const fn = beforeInitOptions[type];
|
|
if (fn) {
|
|
await fn(model, { database: this.app.db });
|
|
}
|
|
});
|
|
|
|
this.app.db.on('fields.afterCreate', afterCreateForReverseField(this.app.db));
|
|
|
|
this.app.db.on('collections.afterCreateWithAssociations', async (model, { context, transaction }) => {
|
|
if (context) {
|
|
await model.migrate({
|
|
isNew: true,
|
|
transaction,
|
|
});
|
|
}
|
|
});
|
|
|
|
this.app.db.on('fields.afterCreate', async (model: FieldModel, { context, transaction }) => {
|
|
if (context) {
|
|
await model.migrate({
|
|
isNew: true,
|
|
transaction,
|
|
});
|
|
}
|
|
});
|
|
|
|
// after migrate
|
|
this.app.db.on('fields.afterCreate', afterCreateForForeignKeyField(this.app.db));
|
|
|
|
this.app.db.on('fields.afterUpdate', async (model: FieldModel, { context, transaction }) => {
|
|
const prevOptions = model.previous('options');
|
|
const currentOptions = model.get('options');
|
|
|
|
if (context) {
|
|
const prev = prevOptions['unique'];
|
|
const next = currentOptions['unique'];
|
|
|
|
if (Boolean(prev) !== Boolean(next)) {
|
|
await model.migrate({ transaction });
|
|
}
|
|
}
|
|
|
|
const prevDefaultValue = prevOptions['defaultValue'];
|
|
const currentDefaultValue = currentOptions['defaultValue'];
|
|
|
|
if (prevDefaultValue != currentDefaultValue) {
|
|
await model.syncDefaultValue({ transaction, defaultValue: currentDefaultValue });
|
|
}
|
|
});
|
|
|
|
this.app.db.on('fields.afterSaveWithAssociations', async (model, { context, transaction }) => {
|
|
if (context) {
|
|
await model.load({ transaction });
|
|
}
|
|
});
|
|
|
|
// before field remove
|
|
this.app.db.on('fields.beforeDestroy', beforeDestroyForeignKey(this.app.db));
|
|
this.app.db.on('fields.beforeDestroy', async (model, options) => {
|
|
await model.remove(options);
|
|
});
|
|
|
|
this.app.db.on('collections.beforeDestroy', async (model, options) => {
|
|
await model.remove(options);
|
|
});
|
|
|
|
this.app.on('afterLoad', async (app, options) => {
|
|
if (options?.method === 'install') {
|
|
return;
|
|
}
|
|
const exists = await this.app.db.collectionExistsInDb('collections');
|
|
if (exists) {
|
|
await this.app.db.getRepository<CollectionRepository>('collections').load();
|
|
}
|
|
});
|
|
|
|
this.app.resourcer.use(async (ctx, next) => {
|
|
const { resourceName, actionName } = ctx.action;
|
|
if (resourceName === 'collections.fields' && actionName === 'update') {
|
|
const { updateAssociationValues = [] } = ctx.action.params;
|
|
updateAssociationValues.push('uiSchema');
|
|
ctx.action.mergeParams({
|
|
updateAssociationValues,
|
|
});
|
|
}
|
|
await next();
|
|
});
|
|
|
|
this.app.acl.allow('collections', 'list', 'loggedIn');
|
|
this.app.acl.allow('collections', ['create', 'update', 'destroy'], 'allowConfigure');
|
|
}
|
|
|
|
async load() {
|
|
await this.app.db.import({
|
|
directory: path.resolve(__dirname, './collections'),
|
|
});
|
|
|
|
const errorHandlerPlugin = <PluginErrorHandler>this.app.getPlugin('error-handler');
|
|
errorHandlerPlugin.errorHandler.register(
|
|
(err) => {
|
|
return err instanceof UniqueConstraintError;
|
|
},
|
|
(err, ctx) => {
|
|
return ctx.throw(400, ctx.t(`The value of ${Object.keys(err.fields)} field duplicated`));
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
export default CollectionManagerPlugin;
|