feat: generate reverse field for linkTo fields
This commit is contained in:
parent
a771aade5c
commit
8bd5a83947
11
packages/api/src/migrations/sync.ts
Normal file
11
packages/api/src/migrations/sync.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import Database from '@nocobase/database';
|
||||
import api from '../app';
|
||||
|
||||
(async () => {
|
||||
await api.loadPlugins();
|
||||
const database: Database = api.database;
|
||||
await database.sync({
|
||||
// tables: ['collections', 'fields', 'actions', 'views', 'tabs'],
|
||||
});
|
||||
await database.close();
|
||||
})();
|
@ -10,6 +10,12 @@ const [CollectionsProvider, useCollectionsContext] = constate(() => {
|
||||
findCollection(name) {
|
||||
return result?.data?.find((item) => item.name === name);
|
||||
},
|
||||
async loadCollections(field: any) {
|
||||
return result?.data?.map((item: any) => ({
|
||||
label: item.title,
|
||||
value: item.name,
|
||||
}));
|
||||
},
|
||||
getFieldsByCollection(collectionName) {
|
||||
const collection = result?.data?.find((item) => item.name === collectionName);
|
||||
return collection?.generalFields;
|
||||
|
@ -1370,6 +1370,7 @@ AddNew.FormItem = observer((props: any) => {
|
||||
const { schema, insertBefore, insertAfter, appendChild, deepRemove } =
|
||||
useDesignable();
|
||||
const path = useSchemaPath();
|
||||
const { loadCollections } = useCollectionsContext();
|
||||
const { collection, fields, refresh } = useCollectionContext();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const displayed = useDisplayedMapContext();
|
||||
@ -1562,7 +1563,7 @@ AddNew.FormItem = observer((props: any) => {
|
||||
const values = await FormDialog(`添加字段`, () => {
|
||||
return (
|
||||
<FormLayout layout={'vertical'}>
|
||||
<SchemaField schema={item} />
|
||||
<SchemaField scope={{ loadCollections }} schema={item} />
|
||||
</FormLayout>
|
||||
);
|
||||
}).open({
|
||||
|
@ -405,6 +405,7 @@ const useTableColumns = () => {
|
||||
function AddColumn() {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const { appendChild, remove } = useDesignable();
|
||||
const { loadCollections } = useCollectionsContext();
|
||||
const { collection, fields, refresh } = useCollectionContext();
|
||||
const displayed = useDisplayedMapContext();
|
||||
const { service } = useTable();
|
||||
@ -592,7 +593,7 @@ function AddColumn() {
|
||||
const values = await FormDialog(`添加字段`, () => {
|
||||
return (
|
||||
<FormLayout layout={'vertical'}>
|
||||
<SchemaField schema={item} />
|
||||
<SchemaField scope={{ loadCollections }} schema={item} />
|
||||
</FormLayout>
|
||||
);
|
||||
}).open({
|
||||
|
@ -18,40 +18,40 @@ export default async function() {
|
||||
addAll(database.getModel(table.options.name));
|
||||
});
|
||||
|
||||
const Collection = database.getModel('collections');
|
||||
Collection.addHook('afterCreate', async (model, options) => {
|
||||
if (!model.get('logging')) {
|
||||
return;
|
||||
}
|
||||
// const Collection = database.getModel('collections');
|
||||
// Collection.addHook('afterCreate', async (model, options) => {
|
||||
// if (!model.get('logging')) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
const { transaction = await model.sequelize.transaction() } = options;
|
||||
// const { transaction = await model.sequelize.transaction() } = options;
|
||||
|
||||
const exists = await model.countFields({
|
||||
where: {
|
||||
dataType: { [Op.iLike]: 'hasMany' },
|
||||
name: 'action_logs'
|
||||
},
|
||||
transaction
|
||||
});
|
||||
// const exists = await model.countFields({
|
||||
// where: {
|
||||
// dataType: { [Op.iLike]: 'hasMany' },
|
||||
// name: 'action_logs'
|
||||
// },
|
||||
// transaction
|
||||
// });
|
||||
|
||||
if (!exists) {
|
||||
await model.createSystemField({
|
||||
interface: 'linkTo',
|
||||
dataType: 'hasMany',
|
||||
name: 'action_logs',
|
||||
target: 'action_logs',
|
||||
title: '数据动态',
|
||||
foreignKey: 'index',
|
||||
state: 0,
|
||||
scope: {
|
||||
collection_name: model.get('name')
|
||||
},
|
||||
constraints: false
|
||||
}, { transaction });
|
||||
}
|
||||
// if (!exists) {
|
||||
// await model.createSystemField({
|
||||
// interface: 'linkTo',
|
||||
// dataType: 'hasMany',
|
||||
// name: 'action_logs',
|
||||
// target: 'action_logs',
|
||||
// title: '数据动态',
|
||||
// foreignKey: 'index',
|
||||
// state: 0,
|
||||
// scope: {
|
||||
// collection_name: model.get('name')
|
||||
// },
|
||||
// constraints: false
|
||||
// }, { transaction });
|
||||
// }
|
||||
|
||||
if (!options.transaction) {
|
||||
await transaction.commit();
|
||||
}
|
||||
});
|
||||
// if (!options.transaction) {
|
||||
// await transaction.commit();
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import { cloneDeep, omit } from 'lodash';
|
||||
export const create = async (ctx: actions.Context, next: actions.Next) => {
|
||||
await actions.common.create(ctx, async () => {});
|
||||
const { associated } = ctx.action.params;
|
||||
await ctx.body.generateReverseField();
|
||||
await associated.migrate();
|
||||
// console.log('associated.migrate');
|
||||
await next();
|
||||
|
@ -38,6 +38,17 @@ export const createOrUpdate = async (ctx: actions.Context, next: actions.Next) =
|
||||
})
|
||||
}
|
||||
await collection.updateAssociations(values);
|
||||
|
||||
const fields = await collection.getGeneralFields({
|
||||
where: {
|
||||
interface: 'linkTo',
|
||||
}
|
||||
});
|
||||
|
||||
for (const field of fields) {
|
||||
await field.generateReverseField();
|
||||
}
|
||||
|
||||
await collection.migrate();
|
||||
} catch (error) {
|
||||
// console.log('error.errors', error.errors)
|
||||
|
@ -46,12 +46,18 @@ export default {
|
||||
foreignKey: 'parentKey',
|
||||
},
|
||||
{
|
||||
interface: 'linkTo',
|
||||
type: 'belongsTo',
|
||||
name: 'collection',
|
||||
target: 'collections',
|
||||
targetKey: 'name',
|
||||
},
|
||||
{
|
||||
type: 'belongsTo',
|
||||
name: 'reverseField',
|
||||
target: 'fields',
|
||||
sourceKey: 'key',
|
||||
foreignKey: 'reverseKey',
|
||||
},
|
||||
{
|
||||
type: 'belongsTo',
|
||||
name: 'uiSchema',
|
||||
|
@ -48,4 +48,54 @@ export class Field extends Model {
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
async generateReverseField(opts: any = {}) {
|
||||
const { migrate = true } = opts;
|
||||
if (this.get('interface') !== 'linkTo') {
|
||||
return;
|
||||
}
|
||||
if (this.get('reverseKey')) {
|
||||
return;
|
||||
}
|
||||
const fieldCollection = await this.getCollection();
|
||||
const options: any = this.get('options') || {};
|
||||
const Collection = this.database.getModel('collections');
|
||||
let collection = await Collection.findOne({
|
||||
where: {
|
||||
name: options.target,
|
||||
},
|
||||
});
|
||||
if (!collection) {
|
||||
return;
|
||||
}
|
||||
const reverseField = await collection.createField({
|
||||
interface: 'linkTo',
|
||||
dataType: 'belongsToMany',
|
||||
through: options.through,
|
||||
foreignKey: options.otherKey,
|
||||
otherKey: options.foreignKey,
|
||||
sourceKey: options.targetKey,
|
||||
targetKey: options.sourceKey,
|
||||
target: this.get('collection_name'),
|
||||
reverseKey: this.get('key'),
|
||||
});
|
||||
await reverseField.updateAssociations({
|
||||
uiSchema: {
|
||||
type: 'array',
|
||||
title: `${fieldCollection?.title}`,
|
||||
'x-component': 'Select.Drawer',
|
||||
'x-component-props': {
|
||||
multiple: true,
|
||||
},
|
||||
'x-decorator': 'FormItem',
|
||||
'x-designable-bar': 'Select.Drawer.DesignableBar',
|
||||
}
|
||||
});
|
||||
await this.update({
|
||||
reverseKey: reverseField.key,
|
||||
});
|
||||
if (migrate) {
|
||||
await collection.migrate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import path from 'path';
|
||||
import { Application } from '@nocobase/server';
|
||||
import { registerModels, Table } from '@nocobase/database';
|
||||
import { registerModels, Table, uid } from '@nocobase/database';
|
||||
import * as models from './models';
|
||||
import { createOrUpdate, findAll } from './actions';
|
||||
import { create } from './actions/fields';
|
||||
@ -27,6 +27,7 @@ export default async function (this: Application, options = {}) {
|
||||
}
|
||||
});
|
||||
Field.beforeUpdate(async (model) => {
|
||||
console.log('beforeUpdate', model.key);
|
||||
if (!model.get('collection_name') && model.get('parentKey')) {
|
||||
const field = await Field.findByPk(model.get('parentKey'));
|
||||
if (field) {
|
||||
@ -37,8 +38,8 @@ export default async function (this: Application, options = {}) {
|
||||
}
|
||||
}
|
||||
});
|
||||
Field.afterCreate(async (model) => {
|
||||
console.log('afterCreate');
|
||||
Field.afterCreate(async (model, options) => {
|
||||
console.log('afterCreate', model.key, model.get('collection_name'));
|
||||
if (model.get('interface') !== 'subTable') {
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user