2020-10-25 20:14:51 +00:00
|
|
|
/**
|
|
|
|
* @author Martin Karkowski
|
|
|
|
* @email m.karkowski@zema.de
|
|
|
|
* @create date 2020-03-12 11:57:20
|
2020-10-29 18:20:42 +00:00
|
|
|
* @modify date 2020-10-29 09:30:19
|
2020-10-25 20:14:51 +00:00
|
|
|
* @desc [description]
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2020-10-29 18:20:42 +00:00
|
|
|
import { v4 as generateID } from 'uuid';
|
|
|
|
import { dynamicSort } from '../../../../lib/helpers/arrayMethods';
|
2020-10-25 20:14:51 +00:00
|
|
|
import { deepClone } from '../../../../lib/helpers/objectMethods';
|
|
|
|
import { replaceAll } from '../../../../lib/helpers/stringMethods';
|
2020-10-29 18:20:42 +00:00
|
|
|
import { IBaseNodeOptions } from '../interfaces/IBaseNodeOptions';
|
2020-10-30 18:30:59 +00:00
|
|
|
import { IBasicTemplate } from '../interfaces/IBasicTemplate';
|
2020-10-29 18:20:42 +00:00
|
|
|
import { IBaseGraph } from '../interfaces/IGraph';
|
2020-10-25 20:14:51 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Function to Adapt the IDS of a Template
|
|
|
|
* @param template The Template which should be adapted
|
|
|
|
* @param useExistingNodesForEdges Flag, to determine, whether to use unfound Elements or not
|
|
|
|
*/
|
2020-10-30 18:30:59 +00:00
|
|
|
export function adaptIDS(template : IBasicTemplate<any,any>, useExistingNodesForEdges = false) {
|
2020-10-25 20:14:51 +00:00
|
|
|
const ids = {};
|
|
|
|
|
|
|
|
const ret = deepClone(template);
|
|
|
|
|
|
|
|
for (const node of template.nodes) {
|
|
|
|
if (!node.id) {
|
|
|
|
node.id = generateID();
|
|
|
|
}
|
|
|
|
|
|
|
|
ids[node.id] = generateID();
|
|
|
|
}
|
|
|
|
|
|
|
|
const availableIDs = template.nodes.map(node => node.id);
|
|
|
|
|
|
|
|
// Extract the IDS of all Subelements
|
|
|
|
for (const node of template.nodes) {
|
|
|
|
// Check if the Id is assembled like parent.connector,
|
|
|
|
// Then, make shure, only the Parent has been removed
|
|
|
|
for (const id of availableIDs){
|
|
|
|
if (node.id.startsWith(id)){
|
|
|
|
ids[node.id] = node.id.replace(id, ids[id]);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!useExistingNodesForEdges) {
|
|
|
|
ret.edges = ret.edges.filter(edge => {
|
|
|
|
if (ids[edge.from] === undefined || ids[edge.to] === undefined) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
return edge;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Adapt the Edges
|
|
|
|
for (const edge of ret.edges) {
|
|
|
|
edge.id = generateID();
|
|
|
|
|
|
|
|
if (!useExistingNodesForEdges && (ids[edge.from] === undefined || ids[edge.to] === undefined)) {
|
|
|
|
throw Error('Template contains different IDS');
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ids[edge.from]) {
|
|
|
|
edge.from = ids[edge.from];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ids[edge.to]) {
|
|
|
|
edge.to = ids[edge.to];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Adapt the Nodes
|
|
|
|
for (const node of ret.nodes) {
|
|
|
|
node.id = ids[node.id];
|
|
|
|
|
|
|
|
// Replace the Node ID.
|
2020-10-30 18:30:59 +00:00
|
|
|
if (node?.data?.path){
|
2020-10-25 20:14:51 +00:00
|
|
|
node.data.path == replaceAll(node.data.path, node.parent, ids[node.parent])
|
|
|
|
}
|
|
|
|
|
|
|
|
if (node.parent && ids[node.parent] === undefined) {
|
|
|
|
throw Error('Template contains different IDS')
|
|
|
|
} else if (node.parent) {
|
|
|
|
node.parent = ids[node.parent];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Tool To Adapt the Position of a Template
|
|
|
|
* @param template The Template
|
|
|
|
* @param pos The Position to Use.
|
|
|
|
*/
|
2020-10-30 18:30:59 +00:00
|
|
|
export function adaptPositions(template: IBasicTemplate<any,any>, pos: { x: number, y: number }) {
|
2020-10-25 20:14:51 +00:00
|
|
|
if (template.nodes.length > 0) {
|
2020-10-30 18:30:59 +00:00
|
|
|
const deltaX = (pos.x || 0)- (template.nodes[0].x || 0);
|
|
|
|
const deltaY = (pos.y || 0)- (template.nodes[0].y || 0);
|
2020-10-25 20:14:51 +00:00
|
|
|
|
|
|
|
for (const node of template.nodes) {
|
2020-10-30 18:30:59 +00:00
|
|
|
node.x = (node.x || 0) + deltaX;
|
|
|
|
node.y = (node.y || 0) + deltaY;
|
2020-10-25 20:14:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return template;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function to Flatten nested Data.
|
|
|
|
* @param options F
|
|
|
|
*/
|
2020-10-30 18:30:59 +00:00
|
|
|
export function flattenData(options) {
|
|
|
|
const list = new Array<{ index: number, element: IBaseNodeOptions }>();
|
2020-10-25 20:14:51 +00:00
|
|
|
|
|
|
|
for (const node of options) {
|
|
|
|
_flattenDataRecursive(node, list, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Sort the List based on the Porperty */
|
|
|
|
return list.sort(dynamicSort('index')).map(data => data.element);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-10-30 18:30:59 +00:00
|
|
|
function _flattenDataRecursive(options, list = new Array<{ index: number, element: IBaseNodeOptions }>(), index = 0) {
|
2020-10-25 20:14:51 +00:00
|
|
|
|
|
|
|
/** Check if some Connectors are provided or not */
|
|
|
|
if (options.connectors) {
|
|
|
|
|
|
|
|
for (const connector of options.connectors) {
|
|
|
|
/** Make shure it is marked as Connector */
|
|
|
|
connector.isConnector = true;
|
|
|
|
_flattenDataRecursive(connector, list, index + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
options.connectors = undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (options.children) {
|
|
|
|
for (const child of options.children) {
|
|
|
|
child.parent = options.id;
|
|
|
|
_flattenDataRecursive(child, list, index + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
options.children = undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** Push the Own Element to the List */
|
|
|
|
list.push({
|
|
|
|
index,
|
|
|
|
element: options
|
|
|
|
});
|
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2020-10-29 18:20:42 +00:00
|
|
|
/**
|
|
|
|
* Get All Subelements
|
|
|
|
*
|
|
|
|
* @export
|
|
|
|
* @template N
|
|
|
|
* @template E
|
|
|
|
* @param {IBaseGraph<N,E>} network
|
|
|
|
* @param {boolean} [considerChildern=false]
|
|
|
|
* @return {*}
|
|
|
|
*/
|
2020-10-30 18:30:59 +00:00
|
|
|
export function getSelectedElements<N, E>(network: IBaseGraph<N,E>, considerChildern = false){
|
2020-10-25 20:14:51 +00:00
|
|
|
const selected = network.network.getSelectedNodes();
|
|
|
|
|
|
|
|
if (selected.length === 1){
|
|
|
|
const parentID = selected[0];
|
|
|
|
|
2020-10-29 18:20:42 +00:00
|
|
|
const ret: IBaseNodeOptions<N>[] = [network.data.nodes.get(parentID)];
|
2020-10-25 20:14:51 +00:00
|
|
|
|
|
|
|
const selection = network.data.nodes.get({
|
2020-10-29 18:20:42 +00:00
|
|
|
filter(node: IBaseNodeOptions<N>) {
|
2020-10-25 20:14:51 +00:00
|
|
|
if (node.parent === parentID) {
|
|
|
|
if (considerChildern) {
|
|
|
|
return node;
|
|
|
|
} else if (node.isConnector || node.isResizer){
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
ret.push(...selection);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return [];
|
|
|
|
}
|