react-occult
Version:
Layered Information Visualization based on React and D3
100 lines (87 loc) • 2.78 kB
JavaScript
const hierarchyDecorator = (hierarchy, hashEntries, nodeIDAccessor, nodes) => {
if (hierarchy.children) {
hierarchy.children.forEach(child => {
const theseEntries = hashEntries.filter(entry => entry[1] === child.id);
theseEntries.forEach(entry => {
const idNode =
nodes.find(node => nodeIDAccessor(node) === entry[0]) || {};
child.childHash[entry[0]] = {
id: entry[0],
children: [],
childHash: {},
...idNode
};
child.children.push(child.childHash[entry[0]]);
});
if (child.children.length > 0) {
hierarchyDecorator(child, hashEntries, nodeIDAccessor, nodes);
}
});
}
};
const softStack = (
edges,
nodes,
sourceAccessor,
targetAccessor,
nodeIDAccessor
) => {
let hierarchy = { id: 'root-generated', children: [], childHash: {} };
const discoveredHierarchyHash = {};
const targetToSourceHash = {};
let hasLogicalRoot = true;
let isHierarchical = true;
for (let i = 0; i < edges.length; i++) {
const edge = edges[i];
const source = sourceAccessor(edge);
const target = targetAccessor(edge);
const sourceID =
typeof source === 'object' ? nodeIDAccessor(source) : source;
const targetID =
typeof target === 'object' ? nodeIDAccessor(target) : target;
targetToSourceHash[targetID] = sourceID;
if (!discoveredHierarchyHash[sourceID]) {
discoveredHierarchyHash[sourceID] = targetID;
} else {
isHierarchical = false;
break;
}
}
if (isHierarchical) {
const hashEntries = Object.values(discoveredHierarchyHash);
hashEntries.forEach(entry => {
const target = entry;
if (!discoveredHierarchyHash[target]) {
discoveredHierarchyHash[target] = 'root-generated';
const idNode =
nodes.find(node => nodeIDAccessor(node) === target) || {};
hierarchy.childHash[target] = {
id: target,
children: [],
childHash: {},
...idNode
};
hierarchy.children.push(hierarchy.childHash[target]);
}
});
hierarchyDecorator(hierarchy, hashEntries, nodeIDAccessor, nodes);
nodes.forEach(node => {
const nodeID = nodeIDAccessor(node);
if (!discoveredHierarchyHash[nodeID] && !targetToSourceHash[nodeID]) {
hierarchy.children.push({
id: nodeID,
children: [],
childHash: {},
...node
});
}
});
if (hierarchy.children.length === 1) {
hierarchy = hierarchy.children[0];
hasLogicalRoot = false;
}
return { hierarchy, isHierarchical: true, hasLogicalRoot };
}
return { hierarchy: {}, isHierarchical: false, hasLogicalRoot: false };
};
export default softStack;