195 lines
5.9 KiB
JavaScript
195 lines
5.9 KiB
JavaScript
import assert from 'assert';
|
||
import { unset } from 'oak-domain/lib/utils/lodash';
|
||
const SystemEntities = [
|
||
'modi',
|
||
'modiEntity',
|
||
'oper',
|
||
'operEntity',
|
||
'userEntityGrant',
|
||
'relation',
|
||
'userRelation',
|
||
'actionAuth',
|
||
'relationAuth',
|
||
'i18n',
|
||
'path',
|
||
'userEntityClaim'
|
||
];
|
||
function buildEntityGraph(schema) {
|
||
const graph = {};
|
||
const addToGraph = (entity, path, descendant, type) => {
|
||
if (graph[entity]) {
|
||
graph[entity].push({
|
||
path,
|
||
entity: descendant,
|
||
type,
|
||
});
|
||
}
|
||
else {
|
||
graph[entity] = [
|
||
{
|
||
path,
|
||
entity: descendant,
|
||
type,
|
||
}
|
||
];
|
||
}
|
||
};
|
||
for (const entity in schema) {
|
||
if (SystemEntities.includes(entity)) {
|
||
continue;
|
||
}
|
||
const { attributes } = schema[entity];
|
||
for (const attr in attributes) {
|
||
const attrDef = attributes[attr];
|
||
if (attr === 'entity') {
|
||
attrDef.ref?.forEach((ele) => {
|
||
addToGraph(entity, ele, ele, 'entity');
|
||
addToGraph(ele, `${entity}$entity`, entity, 'entityOtm');
|
||
});
|
||
}
|
||
else if (attrDef.ref) {
|
||
const attr2 = attr.slice(0, attr.length - 2);
|
||
addToGraph(entity, attr2, attrDef.ref, 'attr');
|
||
addToGraph(attrDef.ref, `${entity}$${attr2}`, entity, 'attrOtm');
|
||
}
|
||
}
|
||
}
|
||
unset(graph, 'user');
|
||
return graph;
|
||
}
|
||
export default OakComponent({
|
||
entity: 'path',
|
||
isList: false,
|
||
projection: {
|
||
id: 1,
|
||
destEntity: 1,
|
||
value: 1,
|
||
sourceEntity: 1,
|
||
desc: 1,
|
||
recursive: 1,
|
||
},
|
||
formData({ data }) {
|
||
const { graph } = this.state;
|
||
const recursivable = data?.sourceEntity && graph && graph[data.sourceEntity]?.find(ele => ele.entity === data.sourceEntity);
|
||
return {
|
||
isCreate: data?.$$createAt$$ === 1,
|
||
path: data,
|
||
recursivable,
|
||
oakExecutable: this.tryExecute(),
|
||
};
|
||
},
|
||
properties: {
|
||
onConfirmed: () => undefined,
|
||
entity: '',
|
||
},
|
||
data: {
|
||
entities: [],
|
||
graph: {},
|
||
pathChoice: [],
|
||
pathChosen: [],
|
||
recursivable: false,
|
||
legalSourceEntity: false,
|
||
destEntityFixed: false,
|
||
},
|
||
lifetimes: {
|
||
ready() {
|
||
const schema = this.features.cache.getSchema();
|
||
const entities = Object.keys(schema).filter(ele => !SystemEntities.includes(ele) && ele !== 'user');
|
||
const graph = buildEntityGraph(schema);
|
||
const { entity } = this.props;
|
||
this.setState({
|
||
entities,
|
||
graph,
|
||
destEntityFixed: !!entity,
|
||
legalSourceEntity: !this.isCreation(),
|
||
}, () => {
|
||
this.updateDestEntity(entity);
|
||
});
|
||
}
|
||
},
|
||
methods: {
|
||
updateDestEntity(de) {
|
||
const { graph } = this.state;
|
||
if (de) {
|
||
const pathChoice = (graph[de] || []).filter(ele => {
|
||
if (ele.entity === de) {
|
||
return false;
|
||
}
|
||
return true;
|
||
});
|
||
const schema = this.features.cache.getSchema();
|
||
const legalSourceEntity = !!schema[de].relation?.length || de === 'user';
|
||
this.update({
|
||
destEntity: de,
|
||
sourceEntity: de,
|
||
value: '',
|
||
recursive: false,
|
||
desc: null,
|
||
});
|
||
this.setState({
|
||
pathChoice,
|
||
pathChosen: [],
|
||
legalSourceEntity,
|
||
});
|
||
}
|
||
else {
|
||
this.update({
|
||
value: '',
|
||
});
|
||
this.setState({
|
||
pathChosen: [],
|
||
});
|
||
}
|
||
},
|
||
selectPath(value) {
|
||
const { pathChoice, pathChosen } = this.state;
|
||
const choice = pathChoice.find(ele => ele.path === value);
|
||
assert(choice);
|
||
const pathChosen2 = pathChosen.concat([choice]);
|
||
const { graph } = this.state;
|
||
const entities = pathChosen2.map(ele => ele.entity);
|
||
// path按道理不应该产生重复,如果有出现重复再处理 by Xc 20240628
|
||
const pathChoice2 = (graph[choice.entity] || []).filter(ele => {
|
||
if (!entities.includes(ele.entity)) {
|
||
return true;
|
||
}
|
||
return false;
|
||
});
|
||
const schema = this.features.cache.getSchema();
|
||
const legalSourceEntity = !!schema[choice.entity].relation?.length || !!choice.entity;
|
||
this.setState({
|
||
pathChoice: pathChoice2,
|
||
pathChosen: pathChosen2,
|
||
legalSourceEntity,
|
||
});
|
||
this.update({
|
||
sourceEntity: choice.entity,
|
||
recursive: false,
|
||
desc: null,
|
||
});
|
||
},
|
||
resetPath() {
|
||
const { path } = this.state;
|
||
this.updateDestEntity(path.destEntity);
|
||
},
|
||
clearDestEntity() {
|
||
this.clean();
|
||
this.setState({
|
||
legalSourceEntity: false,
|
||
});
|
||
},
|
||
async confirm() {
|
||
const { pathChosen, isCreate } = this.state;
|
||
if (isCreate) {
|
||
const value = pathChosen.map(ele => ele.path).join('.');
|
||
this.update({
|
||
value,
|
||
});
|
||
}
|
||
const { onConfirmed } = this.props;
|
||
assert(onConfirmed);
|
||
onConfirmed();
|
||
}
|
||
}
|
||
});
|