codeatlas-enterprise / frontend /src /utils /graphTransformers.js
Shivam311's picture
feat: CodeAtlas Enterprise - IBM Bob Engineering Intelligence Platform
3a7842d
Raw
History Blame Contribute Delete
3.84 kB
const LAYER_ORDER = ['frontend', 'api', 'backend', 'middleware', 'auth', 'database', 'utility'];
export function toArray(value) {
if (Array.isArray(value)) return value;
if (value === null || value === undefined || value === '') return [];
return [value];
}
export function normalizeSteps(value) {
if (Array.isArray(value)) return value.map((step) => String(step)).filter(Boolean);
if (typeof value === 'string') {
const parts = value.split(/\s*(?:->|→|=>)\s*/).map((step) => step.trim()).filter(Boolean);
return parts.length > 1 ? parts : [value];
}
return toArray(value).map((step) => String(step)).filter(Boolean);
}
export function normalizeWorkflows(workflows = []) {
return toArray(workflows)
.map((workflow, index) => {
if (workflow && typeof workflow === 'object') {
return {
...workflow,
name: workflow.name || workflow.title || `Workflow ${index + 1}`,
steps: normalizeSteps(workflow.steps || workflow.flow || workflow.sequence || workflow.description),
services_involved: toArray(workflow.services_involved || workflow.services || workflow.components),
};
}
return {
name: `Workflow ${index + 1}`,
steps: normalizeSteps(workflow),
services_involved: [],
};
})
.filter((workflow) => workflow.steps.length > 0);
}
export function transformGraphData(rawGraph) {
if (!rawGraph) return { nodes: [], edges: [], metadata: {}, workflows: [] };
const { nodes = [], edges = [], metadata = {}, workflows = [] } = rawGraph;
const layers = {};
nodes.forEach((node) => {
const type = node.data?.type || 'utility';
const layer = LAYER_ORDER.indexOf(type);
const key = layer >= 0 ? layer : LAYER_ORDER.length;
layers[key] = layers[key] || [];
layers[key].push(node);
});
const transformedNodes = [];
Object.keys(layers)
.sort((a, b) => Number(a) - Number(b))
.forEach((layerKey, layerIndex) => {
const layerNodes = layers[layerKey];
const offset = ((layerNodes.length - 1) * 150) / 2;
layerNodes.forEach((node, nodeIndex) => {
transformedNodes.push({
...node,
data: {
...node.data,
files: toArray(node.data?.files),
},
position: {
x: layerIndex * 310 + 60,
y: nodeIndex * 170 + 260 - offset,
},
});
});
});
return { nodes: transformedNodes, edges, metadata, workflows: normalizeWorkflows(workflows) };
}
export function highlightImpactedNodes(nodes, impactedServiceNames = []) {
return nodes.map((node) => ({
...node,
data: {
...node.data,
highlighted: impactedServiceNames.some((name) =>
node.data?.label?.toLowerCase().includes(String(name).toLowerCase()),
),
},
}));
}
export function workflowsToReactFlow(workflows = []) {
const nodes = [];
const edges = [];
normalizeWorkflows(workflows).forEach((workflow, workflowIndex) => {
const steps = workflow.steps;
steps.forEach((step, stepIndex) => {
const id = `wf_${workflowIndex}_${stepIndex}`;
nodes.push({
id,
type: 'workflowNode',
position: { x: stepIndex * 220 + 60, y: workflowIndex * 190 + 90 },
data: {
label: step,
nodeType: stepIndex === 0 ? 'start' : stepIndex === steps.length - 1 ? 'process' : 'process',
color: stepIndex === 0 ? '#10B981' : '#3B82F6',
description: workflow.name,
},
});
if (stepIndex > 0) {
edges.push({
id: `wf_e_${workflowIndex}_${stepIndex}`,
source: `wf_${workflowIndex}_${stepIndex - 1}`,
target: id,
type: 'workflowEdge',
animated: true,
});
}
});
});
return { nodes, edges };
}