feat: generate reverse field for linkTo fields

This commit is contained in:
chenos 2021-09-03 14:08:15 +08:00
parent a771aade5c
commit 8bd5a83947
10 changed files with 126 additions and 38 deletions

View 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();
})();

View File

@ -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;

View File

@ -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({

View File

@ -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({

View File

@ -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();
// }
// });
}

View File

@ -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();

View File

@ -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)

View File

@ -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',

View File

@ -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();
}
}
}

View File

@ -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;
}