nocobase/packages/plugin-pages/src/server.ts
2021-04-06 19:52:01 +08:00

257 lines
7.9 KiB
TypeScript

import path from 'path';
import Database from '@nocobase/database';
import Resourcer from '@nocobase/resourcer';
import getCollection from './actions/getCollection';
import getView from './actions/getView';
import getRoutes from './actions/getRoutes';
import getPageInfo from './actions/getPageInfo';
import * as rolesPagesActions from './actions/roles.pages';
import getCollections from './actions/getCollections';
import menusList from './actions/menus:list';
import getTree from './actions/getTree';
import getInfo from './actions/getInfo';
import viewGetInfo from './actions/views_v2:getInfo';
import { RANDOMSTRING } from './fields/randomString';
import { registerFields, registerModels } from '@nocobase/database';
import { BaseModel } from './models/BaseModel'
import * as rolesMenusActions from './actions/roles.menus';
import _ from 'lodash';
export default async function (options = {}) {
const database: Database = this.database;
const resourcer: Resourcer = this.resourcer;
registerFields({
RANDOMSTRING,
});
registerModels({
BaseModelV2: BaseModel,
});
database.import({
directory: path.resolve(__dirname, 'collections'),
});
resourcer.use(async (ctx, next) => {
const { actionName, resourceName, resourceKey } = ctx.action.params;
if (resourceName === 'system_settings' && actionName === 'get') {
const SystemSetting = database.getModel('system_settings');
let model = await SystemSetting.findOne();
if (!model) {
model = await SystemSetting.create();
}
ctx.action.mergeParams({
resourceKey: model.id,
});
}
await next();
});
resourcer.use(async (ctx, next) => {
const { actionName, resourceName, values } = ctx.action.params;
if (resourceName === 'menus' && ['create', 'update'].includes(actionName)) {
if (values.parent) {
delete values.parent.children;
ctx.action.mergeParams({
values: {...values},
}, {
payload: 'replace',
});
}
}
await next();
});
resourcer.use(async (ctx, next) => {
await next();
const { actionName, resourceName } = ctx.action.params;
if (resourceName === 'menus' && actionName === 'get') {
const menu = ctx.body;
const items = menu.get('views') || [];
const View = database.getModel('views_v2');
for (const item of items) {
if (!(item.view && item.view.id)) {
continue;
}
const view = await View.findOne(View.parseApiJson({
filter: {
id: item.view.id,
},
fields: {
appends: ['collection', 'targetField', 'targetView'],
},
}));
if (!view) {
continue;
}
const details = view.get(`options.x-${view.type}-props.details`);
if (!Array.isArray(details)) {
item.view = view;
continue;
}
for (const detail of details) {
if (!(detail.view && detail.view.id)) {
continue;
}
const detailView = await View.findOne(View.parseApiJson({
filter: {
id: detail.view.id,
},
fields: {
appends: ['collection', 'targetField', 'targetView'],
},
}));
if (!detailView) {
continue;
}
detail.view = detailView;
}
view.set(`options.x-${view.type}-props.details`, details);
item.view = view;
}
menu.set('views', items);
}
});
resourcer.registerActionHandler('getCollection', getCollection);
resourcer.registerActionHandler('getView', getView);
resourcer.registerActionHandler('getPageInfo', getPageInfo);
resourcer.registerActionHandler('getCollections', getCollections);
resourcer.registerActionHandler('pages:getRoutes', getRoutes);
resourcer.registerActionHandler('menus:getTree', getTree);
resourcer.registerActionHandler('menus:getInfo', getInfo);
resourcer.registerActionHandler('views_v2:getInfo', viewGetInfo);
resourcer.registerActionHandler('menus:list', menusList);
Object.keys(rolesPagesActions).forEach(actionName => {
resourcer.registerActionHandler(`roles.pages:${actionName}`, rolesPagesActions[actionName]);
});
Object.keys(rolesMenusActions).forEach(actionName => {
resourcer.registerActionHandler(`roles.menus:${actionName}`, rolesMenusActions[actionName]);
});
const createDetailsViews = async (model, options) => {
const data = model.get();
const View = database.getModel('views_v2');
const types = ['table', 'calendar', 'kanban'];
for (const type of types) {
const items = _.get(data, `x-${type}-props.details`) || [];
if (items.length) {
const details = [];
for (const item of items) {
if (item.view) {
if (!item.view.id) {
const view = await View.create(item.view);
await view.updateAssociations(item.view);
item.view.id = view.id;
} else {
const view = await View.findByPk(item.view.id);
if (view) {
await view.update(item.view);
await view.updateAssociations(item.view);
}
}
const view = await View.findOne(View.parseApiJson({
filter: {
id: item.view.id,
},
fields: {
appends: ['collection', 'targetField', 'targetView'],
},
}));
if (view) {
console.log({view});
item.view = view.toJSON();
}
}
details.push(item);
}
model.set(`options.x-${type}-props.details`, details);
}
}
};
database.getModel('views_v2').addHook('beforeCreate', createDetailsViews);
database.getModel('views_v2').addHook('beforeUpdate', createDetailsViews);
database.getModel('views_v2').addHook('beforeSave', async (model, options) => {
const data = model.get();
if (data.type !== 'kanban') {
return;
}
let groupField = _.get(data, `x-kanban-props.groupField`);
if (!groupField) {
return;
}
if (typeof groupField === 'object' && groupField.name) {
groupField = groupField.name;
}
const Field = database.getModel('fields');
let field = await Field.findOne({
where: {
name: `${groupField}_sort`,
collection_name: data.collection_name,
},
});
if (field) {
return;
}
await Field.create({
interface: 'sort',
type: 'sort',
name: `${groupField}_sort`,
// TODO: 不支持相关数据
collection_name: data.collection_name,
scope: [groupField],
title: '看板分组排序',
developerMode: true,
component: {
type: 'sort',
},
});
});
database.getModel('menus').addHook('beforeSave', async (model, options) => {
const { transaction } = options;
// console.log('beforeSave', model.get('views'));
const items = model.get('views');
if (!Array.isArray(items)) {
return;
}
const View = database.getModel('views_v2');
const views = [];
for (const item of items) {
if (item.view) {
if (!item.view.id) {
const view = await View.create(item.view);
await view.updateAssociations(item.view);
item.view.id = view.id;
} else {
const view = await View.findByPk(item.view.id);
await view.update(item.view);
await view.updateAssociations(item.view);
}
const view = await View.findOne(View.parseApiJson({
filter: {
id: item.view.id,
},
fields: {
appends: ['collection', 'targetField', 'targetView'],
},
}));
if (view) {
console.log({view});
item.view = view.toJSON();
}
}
views.push(item);
}
model.set('views', views);
// @ts-ignore
model.changed('views', true);
});
}