General improvements to Access Tree view

This commit is contained in:
carlosmonastyrski
2025-03-28 11:09:56 -03:00
parent 2f4c42482d
commit b0cacc5a4a
9 changed files with 256 additions and 123 deletions

View File

@@ -2,8 +2,10 @@ import Dagre from "@dagrejs/dagre";
import { Edge, Node } from "@xyflow/react";
export const positionElements = (nodes: Node[], edges: Edge[]) => {
const regularNodes = nodes.filter((node) => node.type !== "showMoreButton");
const showMoreNodes = nodes.filter((node) => node.type === "showMoreButton");
const showMoreParentIds = new Set(
showMoreNodes.map((node) => node.data.parentId).filter(Boolean)
);
const nodeMap: Record<string, Node> = {};
const childrenMap: Record<string, string[]> = {};
@@ -17,75 +19,79 @@ export const positionElements = (nodes: Node[], edges: Edge[]) => {
const dagre = new Dagre.graphlib.Graph({ directed: true })
.setDefaultEdgeLabel(() => ({}))
.setGraph({ rankdir: "TB" });
.setGraph({
rankdir: "TB",
nodesep: 50,
ranksep: 70
});
nodes.forEach((node) => {
dagre.setNode(node.id, {
width: node.width || 150,
height: node.height || 40
});
});
edges.forEach((edge) => dagre.setEdge(edge.source, edge.target));
regularNodes.forEach((node) => dagre.setNode(node.id, node));
Dagre.layout(dagre, {});
const positionedNodes = regularNodes.map((node) => {
const positionedNodes = nodes.map((node) => {
const { x, y } = dagre.node(node.id);
const positionedNode = {
...node,
position: {
x: x - (node.width ? node.width / 2 : 0),
y: y - (node.height ? node.height / 2 : 0)
}
};
nodeMap[node.id] = positionedNode;
return positionedNode;
});
const findLastChildNode = (parentId: string): Node | undefined => {
const childrenIds = childrenMap[parentId] || [];
if (childrenIds.length === 0) return undefined;
const childNodes = childrenIds.map((id) => nodeMap[id]).filter(Boolean);
if (childNodes.length === 0) return undefined;
childNodes.sort((a, b) => {
if (a.position.y === b.position.y) {
return b.position.x - a.position.x;
}
return b.position.y - a.position.y;
});
return childNodes[0];
};
const positionedShowMoreNodes = showMoreNodes.map((node) => {
const parentId = node.data.parentId as string;
const parentNode = nodeMap[parentId] || positionedNodes[0];
const lastChildNode = findLastChildNode(parentId);
const referenceNode = lastChildNode || parentNode;
const referenceX = referenceNode.position.x;
const referenceY = referenceNode.position.y;
const referenceWidth = referenceNode.width || 150;
const buttonX = referenceX + referenceWidth - 85;
const buttonY = referenceY - 25;
if (node.type === "role") {
return {
...node,
position: {
x: x - (node.width ? node.width / 2 : 0),
y: y - 150
}
};
}
return {
...node,
position: {
x: buttonX,
y: buttonY
}
x: x - (node.width ? node.width / 2 : 0),
y: y - (node.height ? node.height / 2 : 0)
},
style: node.type === "showMoreButton" ? { ...node.style, zIndex: 10 } : node.style
};
});
positionedNodes.forEach((node) => {
nodeMap[node.id] = node;
});
Array.from(showMoreParentIds).forEach((parentId) => {
const showMoreNodeIndex = positionedNodes.findIndex(
(node) => node.type === "showMoreButton" && node.data.parentId === parentId
);
if (showMoreNodeIndex !== -1) {
const siblings = positionedNodes.filter(
(node) => node.data?.parentId === parentId && node.type !== "showMoreButton"
);
if (siblings.length > 0) {
const rightmostSibling = siblings.reduce(
(rightmost, current) => (current.position.x > rightmost.position.x ? current : rightmost),
siblings[0]
);
positionedNodes[showMoreNodeIndex] = {
...positionedNodes[showMoreNodeIndex],
position: {
x: rightmostSibling.position.x + (rightmostSibling.width || 150) + 30,
y: rightmostSibling.position.y
}
};
}
}
});
return {
nodes: [...positionedNodes, ...positionedShowMoreNodes],
nodes: positionedNodes,
edges
};
};