contextMenuFactory
This commit is contained in:
parent
e88b843f0a
commit
911b22ccd5
|
|
@ -10,6 +10,7 @@ interface IMenu<ED extends EntityDict & BaseEntityDict, T extends keyof ED> {
|
|||
entity: T;
|
||||
action: ED[T]['Action'];
|
||||
data?: ED[T]['Update']['data'];
|
||||
paths?: string[];
|
||||
}
|
||||
interface IMenuWrapper<ED extends EntityDict & BaseEntityDict, T extends keyof ED> extends IMenu<ED, T> {
|
||||
filtersMaker: (entity: keyof ED, entityId: string) => Array<ED[T]['Selection']['filter']>;
|
||||
|
|
@ -21,6 +22,6 @@ export declare class ContextMenuFactory<ED extends EntityDict & BaseEntityDict,
|
|||
private makeMenuWrappers;
|
||||
constructor(cache: Cache<ED, Cxt, FrontCxt, AD>, cascadePathGraph: AuthCascadePath<ED>[]);
|
||||
setMenus(menus: IMenu<ED, keyof ED>[]): void;
|
||||
getMenusByContext(entity: keyof ED, entityId: string): IMenu<ED, keyof ED>[];
|
||||
getMenusByContext<OMenu extends IMenu<ED, keyof ED>>(entity: keyof ED, entityId: string): OMenu[];
|
||||
}
|
||||
export {};
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ var assert_1 = tslib_1.__importDefault(require("assert"));
|
|||
var lodash_1 = require("oak-domain/lib/utils/lodash");
|
||||
var filter_1 = require("oak-domain/lib/store/filter");
|
||||
var Feature_1 = require("../types/Feature");
|
||||
var relation_1 = require("oak-domain/lib/store/relation");
|
||||
;
|
||||
;
|
||||
var ContextMenuFactory = /** @class */ (function (_super) {
|
||||
|
|
@ -17,6 +18,7 @@ var ContextMenuFactory = /** @class */ (function (_super) {
|
|||
return _this;
|
||||
}
|
||||
ContextMenuFactory.prototype.makeMenuWrappers = function (menus) {
|
||||
var _this = this;
|
||||
var destEntities = (0, lodash_1.uniq)(menus.map(function (ele) { return ele.entity; }));
|
||||
var pathMap = {};
|
||||
this.cascadePathGraph.forEach(function (path) {
|
||||
|
|
@ -33,16 +35,41 @@ var ContextMenuFactory = /** @class */ (function (_super) {
|
|||
}
|
||||
});
|
||||
return menus.map(function (menu) {
|
||||
var destEntity = menu.entity;
|
||||
var destEntity = menu.entity, cascadePaths = menu.paths;
|
||||
var filtersMaker = function (sourceEntity, entityId) {
|
||||
// 在cascadePathMap中找到可能的路径并构建对应的filter
|
||||
var paths = pathMap[destEntity].filter(function (ele) { return ele[2] === sourceEntity; });
|
||||
var paths = pathMap[destEntity].filter(function (ele) {
|
||||
if (cascadePaths) {
|
||||
(0, assert_1.default)(cascadePaths.length > 0);
|
||||
return ele[2] === sourceEntity && cascadePaths.includes(ele[1]);
|
||||
}
|
||||
return ele[2] === sourceEntity;
|
||||
});
|
||||
return paths.map(function (path) {
|
||||
var p = path[1];
|
||||
var p2 = p.concat('Id');
|
||||
var filter = {};
|
||||
(0, lodash_1.set)(filter, p2, entityId);
|
||||
return filter;
|
||||
var ps = p.split('.');
|
||||
var makeFilterInner = function (entity, idx) {
|
||||
var _a, _b;
|
||||
var attr = ps[idx];
|
||||
var rel = (0, relation_1.judgeRelation)(_this.cache.getSchema(), entity, attr);
|
||||
if (idx === ps.length - 1) {
|
||||
if (rel === 2) {
|
||||
return {
|
||||
entity: attr,
|
||||
entityId: entityId,
|
||||
};
|
||||
}
|
||||
(0, assert_1.default)(typeof rel === 'string');
|
||||
return _a = {},
|
||||
_a["".concat(attr, "Id")] = entityId,
|
||||
_a;
|
||||
}
|
||||
var e = rel === 2 ? attr : rel;
|
||||
return _b = {},
|
||||
_b[attr] = makeFilterInner(e, idx + 1),
|
||||
_b;
|
||||
};
|
||||
return makeFilterInner(destEntity, 0);
|
||||
});
|
||||
};
|
||||
return Object.assign({}, menu, {
|
||||
|
|
@ -60,9 +87,12 @@ var ContextMenuFactory = /** @class */ (function (_super) {
|
|||
var menus = this.menuWrappers.filter(function (wrapper) {
|
||||
var destEntity = wrapper.entity, data = wrapper.data, filtersMaker = wrapper.filtersMaker, action = wrapper.action;
|
||||
var filters = filtersMaker(entity, entityId);
|
||||
var filter = (0, filter_1.combineFilters)(filters);
|
||||
var allow = _this.cache.checkOperation(destEntity, action, data, filter);
|
||||
return allow;
|
||||
if (filters.length > 0) {
|
||||
var filter = (0, filter_1.combineFilters)(filters);
|
||||
var allow = _this.cache.checkOperation(destEntity, action, data, filter);
|
||||
return allow;
|
||||
}
|
||||
return false;
|
||||
}).map(function (wrapper) { return (0, lodash_1.omit)(wrapper, ['filtersMaker']); });
|
||||
return menus;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@
|
|||
"copy-xml": "copyfiles -u 1 src/**/*.xml lib/ & copyfiles -u 1 src/**/*.wxml lib/",
|
||||
"build": "tsc && npm run copy-js && npm run copy-less && npm run copy-wxs && npm run copy-svg && npm run copy-xml",
|
||||
"test": "ts-node ./test/test2.ts",
|
||||
"prepare": "rimraf node_modules/react & rimraf node_modules/react-dom & rimraf node_modules/react-router"
|
||||
"prepare": "rimraf node_modules/react & rimraf node_modules/react-dom & rimraf node_modules/react-router & rimraf node_modules/react-router-dom"
|
||||
},
|
||||
"main": "lib/index"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,12 +8,14 @@ import { SyncContext } from 'oak-domain/lib/store/SyncRowStore';
|
|||
import { combineFilters } from 'oak-domain/lib/store/filter';
|
||||
import { Cache } from './cache';
|
||||
import { Feature } from '../types/Feature';
|
||||
import { judgeRelation } from 'oak-domain/lib/store/relation';
|
||||
|
||||
interface IMenu<ED extends EntityDict & BaseEntityDict, T extends keyof ED> {
|
||||
name: string;
|
||||
entity: T;
|
||||
action: ED[T]['Action'];
|
||||
data?: ED[T]['Update']['data'];
|
||||
paths?: string[];
|
||||
};
|
||||
|
||||
interface IMenuWrapper<ED extends EntityDict & BaseEntityDict, T extends keyof ED> extends IMenu<ED, T> {
|
||||
|
|
@ -57,19 +59,43 @@ export class ContextMenuFactory<
|
|||
|
||||
return menus.map(
|
||||
(menu) => {
|
||||
const { entity: destEntity } = menu;
|
||||
const { entity: destEntity, paths: cascadePaths } = menu;
|
||||
const filtersMaker = (sourceEntity: keyof ED, entityId: string) => {
|
||||
// 在cascadePathMap中找到可能的路径并构建对应的filter
|
||||
const paths = pathMap[destEntity]!.filter(
|
||||
(ele) => ele[2] === sourceEntity
|
||||
(ele) => {
|
||||
if (cascadePaths) {
|
||||
assert(cascadePaths.length > 0);
|
||||
return ele[2] === sourceEntity && cascadePaths.includes(ele[1]);
|
||||
}
|
||||
return ele[2] === sourceEntity;
|
||||
}
|
||||
);
|
||||
return paths.map(
|
||||
(path) => {
|
||||
const p = path[1];
|
||||
const p2 = p.concat('Id');
|
||||
const filter: ED[keyof ED]['Selection']['filter'] = {};
|
||||
set(filter, p2, entityId);
|
||||
return filter;
|
||||
const ps = p.split('.');
|
||||
const makeFilterInner = (entity: keyof ED, idx: number): ED[keyof ED]['Selection']['filter'] => {
|
||||
const attr = ps[idx];
|
||||
const rel = judgeRelation(this.cache.getSchema(), entity, attr);
|
||||
if (idx === ps.length - 1) {
|
||||
if (rel === 2) {
|
||||
return {
|
||||
entity: attr,
|
||||
entityId,
|
||||
};
|
||||
}
|
||||
assert(typeof rel === 'string');
|
||||
return {
|
||||
[`${attr}Id`]: entityId,
|
||||
};
|
||||
}
|
||||
const e = rel === 2 ? attr : rel as string;
|
||||
return {
|
||||
[attr]: makeFilterInner(e, idx + 1),
|
||||
};
|
||||
}
|
||||
return makeFilterInner(destEntity, 0);
|
||||
}
|
||||
)
|
||||
};
|
||||
|
|
@ -91,19 +117,22 @@ export class ContextMenuFactory<
|
|||
this.menuWrappers = this.makeMenuWrappers(menus);
|
||||
}
|
||||
|
||||
getMenusByContext(entity: keyof ED, entityId: string) {
|
||||
getMenusByContext<OMenu extends IMenu<ED, keyof ED>>(entity: keyof ED, entityId: string) {
|
||||
assert(this.menuWrappers, '应当先调用setMenus才能动态判定菜单');
|
||||
const menus = this.menuWrappers.filter(
|
||||
(wrapper) => {
|
||||
const { entity: destEntity, data, filtersMaker, action } = wrapper;
|
||||
const filters = filtersMaker(entity, entityId);
|
||||
const filter = combineFilters(filters);
|
||||
const allow = this.cache.checkOperation(destEntity, action, data, filter);
|
||||
return allow;
|
||||
if (filters.length > 0) {
|
||||
const filter = combineFilters(filters);
|
||||
const allow = this.cache.checkOperation(destEntity, action, data, filter);
|
||||
return allow;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
).map(
|
||||
(wrapper) => omit(wrapper, ['filtersMaker'])
|
||||
) as IMenu<ED, keyof ED>[];
|
||||
) as OMenu[];
|
||||
|
||||
return menus;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue