#1295 Render fix for flowchart, correct marker handling and some cleanup

This commit is contained in:
Knut Sveidqvist
2020-04-16 19:44:11 +02:00
parent 704d56d193
commit c3f2e8dde1
8 changed files with 126 additions and 318 deletions

View File

@@ -19,7 +19,14 @@ export const clear = () => {
const isDecendant = (id, ancenstorId) => {
// if (id === ancenstorId) return true;
log.info('In isDecendant', ancenstorId, ' ', id, ' = ', decendants[ancenstorId].indexOf(id) >= 0);
log.debug(
'In isDecendant',
ancenstorId,
' ',
id,
' = ',
decendants[ancenstorId].indexOf(id) >= 0
);
if (decendants[ancenstorId].indexOf(id) >= 0) return true;
return false;
@@ -30,7 +37,7 @@ const edgeInCluster = (edge, clusterId) => {
if (!(edge.v === clusterId || edge.w === clusterId)) return false;
if (!decendants[clusterId]) {
log.info('Tilt, ', clustedId, ',not in decendants');
log.debug('Tilt, ', clustedId, ',not in decendants');
return false;
}
@@ -42,50 +49,6 @@ const edgeInCluster = (edge, clusterId) => {
return false;
};
const copyOld = (clusterId, graph, newGraph, rootId) => {
log.info('Copying to', rootId, ' from ', clusterId, graph.node(clusterId), rootId);
const nodes = graph.children(clusterId);
log.info('Copying (nodes)', nodes);
if (nodes) {
nodes.forEach(node => {
if (graph.children(node).length > 0) {
copy(node, graph, newGraph, rootId);
} else {
// if (clusterId === rootId) {
const data = graph.node(node);
log.info('cp ', node, ' to ', rootId, ' with parent ', clusterId); //,node, data, ' parent is ', clusterId);
newGraph.setNode(node, data);
newGraph.setParent(node, clusterId);
const edges = graph.edges(node);
log.trace('Copying Edges', edges);
edges.forEach(edge => {
log.trace('Edge', edge);
const data = graph.edge(edge.v, edge.w, edge.name);
log.trace('Edge data', data, rootId);
try {
// Do not copy edges in and out of the root cluster, they belong to the parent graph
if (edgeInCluster(edge, rootId)) {
log.trace('Copying as ', edge.v, edge.w, data, edge.name);
newGraph.setEdge(edge.v, edge.w, data, edge.name);
log.trace('newGraph edges ', newGraph.edges(), newGraph.edge(newGraph.edges()[0]));
} else {
log.trace('Skipping copy of edge as ', rootId, edge.v, edge.w, clusterId);
}
} catch (e) {
log.error(e);
}
});
// } else {
// log.info('Skipping leaf as root ', rootId, ' !== ', clusterId, ' leaf id = ', node);
// }
}
// log.info('Removing node', node, graphlib.json.write(graph));
log.info('Removing node', node);
graph.removeNode(node);
});
}
// newGraph.setNode(clusterId, graph.node(clusterId));
};
const copy = (clusterId, graph, newGraph, rootId) => {
log.trace(
'Copying children of ',
@@ -103,7 +66,7 @@ const copy = (clusterId, graph, newGraph, rootId) => {
nodes.push(clusterId);
}
log.info('Copying (nodes)', nodes);
log.debug('Copying (nodes)', nodes);
nodes.forEach(node => {
if (graph.children(node).length > 0) {
@@ -113,11 +76,11 @@ const copy = (clusterId, graph, newGraph, rootId) => {
log.trace('cp ', node, ' to ', rootId, ' with parent ', clusterId); //,node, data, ' parent is ', clusterId);
newGraph.setNode(node, data);
if (clusterId !== rootId && node !== clusterId) {
log.info('Setting parent', node, clusterId);
log.debug('Setting parent', node, clusterId);
newGraph.setParent(node, clusterId);
}
const edges = graph.edges(node);
log.info('Copying Edges', edges);
log.debug('Copying Edges', edges);
edges.forEach(edge => {
log.trace('Edge', edge);
const data = graph.edge(edge.v, edge.w, edge.name);
@@ -136,12 +99,12 @@ const copy = (clusterId, graph, newGraph, rootId) => {
}
});
}
log.info('Removing node', node);
log.debug('Removing node', node);
graph.removeNode(node);
});
};
export const extractDecendants = (id, graph) => {
// log.info('Extracting ', id);
// log.debug('Extracting ', id);
const children = graph.children(id);
let res = [].concat(children);
@@ -153,66 +116,6 @@ export const extractDecendants = (id, graph) => {
return res;
};
export const extractGraphFromCluster = (clusterId, graph) => {
log.info('Extracting graph ', clusterId);
const clusterGraph = new graphlib.Graph({
multigraph: true,
compound: true
})
.setGraph({
rankdir: 'TB',
// Todo: set proper spacing
nodesep: 50,
ranksep: 50,
marginx: 8,
marginy: 8
})
.setDefaultEdgeLabel(function() {
return {};
});
// const conf = getConfig().flowchart;
// const nodeSpacing = conf.nodeSpacing || 50;
// const rankSpacing = conf.rankSpacing || 50;
// // Create the input mermaid.graph
// const g = new graphlib.Graph({
// multigraph: true,
// compound: true
// })
// .setGraph({
// rankdir: 'TB',
// nodesep: nodeSpacing,
// ranksep: rankSpacing,
// marginx: 8,
// marginy: 8
// })
// .setDefaultEdgeLabel(function() {
// return {};
// });
log.trace('Extracting before copy', graphlib.json.write(graph));
log.trace('Extracting before copy', graphlib.json.write(graph));
copy(clusterId, graph, clusterGraph, clusterId);
log.trace('Extracting after copy', graphlib.json.write(graph));
log.trace('Extracting after copy', clusterGraph.nodes());
graphs[clusterId] = clusterGraph;
// Remove references to extracted cluster
// graph.edges().forEach(edge => {
// if (isDecendant(edge.v, clusterId) || isDecendant(edge.w, clusterId)) {
// graph.removeEdge(edge);
// }
// });
// graph.nodes().forEach(node => {
// if (isDecendant(node, clusterId)) {
// log.info('Removing ', node, ' from ', clusterId);
// graph.removeNode(node);
// }
// });
return clusterGraph;
};
/**
* Validates the graph, checking that all parent child relation points to existing nodes and that
* edges between nodes also ia correct. When not correct the function logs the discrepancies.
@@ -274,10 +177,10 @@ const getAnchorId = id => {
export const adjustClustersAndEdges = (graph, depth) => {
if (!graph || depth > 10) {
log.info('Opting out, no graph ');
log.debug('Opting out, no graph ');
return;
} else {
log.info('Opting in, graph ');
log.debug('Opting in, graph ');
}
// Go through the nodes and for each cluster found, save a replacment node, this can be used when
// faking a link to a cluster
@@ -291,7 +194,7 @@ export const adjustClustersAndEdges = (graph, depth) => {
findNonClusterChild(id, graph)
);
decendants[id] = extractDecendants(id, graph);
clusterDb[id] = { id: findNonClusterChild(id, graph) };
clusterDb[id] = { id: findNonClusterChild(id, graph), clusterData: graph.node(id) };
}
});
@@ -300,9 +203,9 @@ export const adjustClustersAndEdges = (graph, depth) => {
const children = graph.children(id);
const edges = graph.edges();
if (children.length > 0) {
log.info('Cluster identified', id, decendants);
log.debug('Cluster identified', id, decendants);
edges.forEach(edge => {
// log.info('Edge, decendants: ', edge, decendants[id]);
// log.debug('Edge, decendants: ', edge, decendants[id]);
// Check if any edge leaves the cluster (not the actual cluster, thats a link from the box)
if (edge.v !== id && edge.w !== id) {
@@ -314,8 +217,8 @@ export const adjustClustersAndEdges = (graph, depth) => {
// d1 xor d2 - if either d1 is true and d2 is false or the other way around
if (d1 ^ d2) {
log.info('Edge: ', edge, ' leaves cluster ', id);
log.info('Decendants of ', id, ': ', decendants[id]);
log.debug('Edge: ', edge, ' leaves cluster ', id);
log.debug('Decendants of ', id, ': ', decendants[id]);
clusterDb[id].externalConnections = true;
}
}
@@ -347,7 +250,7 @@ export const adjustClustersAndEdges = (graph, depth) => {
graph.setEdge(v, w, edge, e.name);
}
});
log.info('Adjusted Graph', graphlib.json.write(graph));
log.debug('Adjusted Graph', graphlib.json.write(graph));
log.trace(clusterDb);
@@ -359,91 +262,8 @@ export const adjustClustersAndEdges = (graph, depth) => {
// });
};
export const transformClustersToNodes = (graph, depth) => {
log.info('transformClustersToNodes - ', depth);
if (depth > 10) {
log.error('Bailing out');
return;
}
// For clusters without incoming and/or outgoing edges, create a new cluster-node
// containing the nodes and edges in the custer in a new graph
// for (let i = 0;)
const nodes = graph.nodes();
let hasChildren = false;
for (let i = 0; i < nodes.length; i++) {
const node = nodes[i];
const children = graph.children(node);
hasChildren = hasChildren || children.length > 0;
}
if (!hasChildren) {
log.info('Done, no node has children', graph.nodes());
return;
}
// const clusters = Object.keys(clusterDb);
// clusters.forEach(clusterId => {
log.info('Nodes = ', nodes);
for (let i = 0; i < nodes.length; i++) {
const node = nodes[i];
log.info(
'Handling node',
node,
clusterDb,
clusterDb[node] && !clusterDb[node].externalConnections,
!graph.parent(node),
graph.node(node)
);
// Note that the node might have been removed after the Object.keys call so better check
// that it still is in the game
if (clusterDb[node]) {
if (
!clusterDb[node].externalConnections &&
!graph.parent(node) &&
graph.children(node) &&
graph.children(node).length > 0
) {
log.info('Cluster without external connections', node);
// const parentGraph = parent && graphs[parent] ? graphs[parent] : graph;
// New graph with the nodes in the cluster
log.info('before Extracting ', node, ' parent is ', graph.parent(node));
const clusterGraph = extractGraphFromCluster(node, graph);
if (clusterGraph) {
log.trace('Cluster graph', clusterGraph.nodes());
log.trace('Graph', graph.edges());
log.info('Creating node in original', node, clusterGraph);
// Create a new node in the original graph, this new node is not a cluster
// but a regular node with the cluster content as a new attached graph
graph.setNode(node, {
clusterNode: true,
id: node,
clusterData: clusterDb[node],
labelText: clusterDb[node].labelText,
graph: clusterGraph
});
// if any node in the clusterGraph still has children
transformClustersToNodes(clusterGraph, depth + 1);
}
// The original edges in and out of the cluster is applied
// edges.forEach(edge => {
// log.info('Setting edge', edge);
// const data = graph.edge(edge);
// graph.setEdge(edge.v, edge.w, data);
// });
}
} else {
log.info('Not a cluster ', node);
}
}
};
export const extractor = (graph, depth) => {
log.info('extractor - ', depth, graphlib.json.write(graph), graph.children('D'));
log.debug('extractor - ', depth, graphlib.json.write(graph), graph.children('D'));
if (depth > 10) {
log.error('Bailing out');
return;
@@ -460,16 +280,16 @@ export const extractor = (graph, depth) => {
}
if (!hasChildren) {
log.info('Done, no node has children', graph.nodes());
log.debug('Done, no node has children', graph.nodes());
return;
}
// const clusters = Object.keys(clusterDb);
// clusters.forEach(clusterId => {
log.info('Nodes = ', nodes, depth);
log.debug('Nodes = ', nodes, depth);
for (let i = 0; i < nodes.length; i++) {
const node = nodes[i];
log.info(
log.debug(
'Extracting node',
node,
clusterDb,
@@ -484,7 +304,7 @@ export const extractor = (graph, depth) => {
// that it still is in the game
if (!clusterDb[node]) {
// Skip if the node is not a cluster
log.info('Not a cluster', node, depth);
log.debug('Not a cluster', node, depth);
// break;
} else if (
!clusterDb[node].externalConnections &&
@@ -492,7 +312,7 @@ export const extractor = (graph, depth) => {
graph.children(node) &&
graph.children(node).length > 0
) {
log.info(
log.debug(
'Cluster without external connections, without a parent and with children',
node,
depth
@@ -518,47 +338,14 @@ export const extractor = (graph, depth) => {
graph.setNode(node, {
clusterNode: true,
id: node,
clusterData: clusterDb[node],
clusterData: clusterDb[node].clusterData,
labelText: clusterDb[node].labelText,
graph: clusterGraph
});
log.info('New graph after copy', graphlib.json.write(clusterGraph));
log.info('Old graph after copy', graphlib.json.write(graph));
/*
// New graph with the nodes in the cluster
log.info('before Extracting ', node, ' parent is ', graph.parent(node));
const clusterGraph = extractGraphFromCluster(node, graph);
if (clusterGraph) {
log.trace('Cluster graph', clusterGraph.nodes());
log.trace('Graph', graph.edges());
log.info('Creating node in original', node, clusterGraph);
// Create a new node in the original graph, this new node is not a cluster
// but a regular node with the cluster content as a new attached graph
graph.setNode(node, {
clusterNode: true,
id: node,
clusterData: clusterDb[node],
labelText: clusterDb[node].labelText,
graph: clusterGraph
});
// if any node in the clusterGraph still has children
transformClustersToNodes(clusterGraph, depth + 1);
}
// The original edges in and out of the cluster is applied
// edges.forEach(edge => {
// log.info('Setting edge', edge);
// const data = graph.edge(edge);
// graph.setEdge(edge.v, edge.w, data);
// });
*/
log.debug('New graph after copy', graphlib.json.write(clusterGraph));
log.debug('Old graph after copy', graphlib.json.write(graph));
} else {
log.info(
log.debug(
'Cluster ** ',
node,
' **not meeting the criteria !externalConnections:',
@@ -570,16 +357,16 @@ export const extractor = (graph, depth) => {
graph.children('D'),
depth
);
log.info(clusterDb);
log.debug(clusterDb);
}
}
nodes = graph.nodes();
log.info('New list of nodes', nodes);
log.debug('New list of nodes', nodes);
for (let i = 0; i < nodes.length; i++) {
const node = nodes[i];
const data = graph.node(node);
log.info(' Now next leveö', node, data);
log.debug(' Now next leveö', node, data);
if (data.clusterNode) {
extractor(data.graph, depth + 1);
}