fix(ui) - path analysis hover issue

This commit is contained in:
Shekar Siri 2023-10-23 14:59:51 +02:00
parent 36d7eabbd9
commit 13827e3607
3 changed files with 96 additions and 28 deletions

View file

@ -3,11 +3,23 @@ import { Layer, Rectangle } from 'recharts';
function CustomLink(props: any) {
const [fill, setFill] = React.useState('url(#linkGradient)');
const { payload, sourceX, targetX, sourceY, targetY, sourceControlX, targetControlX, linkWidth, index, activeLink } =
const {
hoveredLinks,
activeLinks,
payload,
sourceX,
targetX,
sourceY,
targetY,
sourceControlX,
targetControlX,
linkWidth,
index,
activeLink
} =
props;
const activeSource = activeLink?.payload.source;
const activeTarget = activeLink?.payload.target;
const isActive = activeSource?.name === payload.source.name && activeTarget?.name === payload.target.name;
const isActive = activeLinks.length > 1 && activeLinks.includes(payload.id);
const isHover = hoveredLinks.length > 1 && hoveredLinks.includes(payload.id);
const onClick = () => {
if (props.onClick) {
@ -34,7 +46,7 @@ function CustomLink(props: any) {
${sourceX},${sourceY - linkWidth / 2}
Z
`}
fill={isActive ? 'rgba(57, 78, 255, 0.5)' : fill}
fill={isActive ? 'rgba(57, 78, 255, 1)' : (isHover ? 'rgba(57, 78, 255, 0.5)' : fill)}
strokeWidth='1'
strokeOpacity={props.strokeOpacity}
onMouseEnter={() => {

View file

@ -27,40 +27,91 @@ interface Props {
data: Data;
nodeWidth?: number;
height?: number;
onChartClick?: (filters: any[]) => void;
}
const SankeyChart: React.FC<Props> = ({
data,
height = 240
height = 240,
onChartClick
}: Props) => {
const [highlightedLinks, setHighlightedLinks] = useState<number[]>([]);
const [hoveredLinks, setHoveredLinks] = useState<number[]>([]);
function buildReversedAdjacencyList(nodes, links) {
const adjList = Array(nodes.length).fill(null).map(() => []);
for (const link of links) {
adjList[link.target].push(link.source);
}
return adjList;
}
function dfs(adjList, start, target, visited, path) {
if (start === target) return [...path, start];
if (visited[start]) return null;
visited[start] = true;
for (const neighbor of adjList[start]) {
const newPath = dfs(adjList, neighbor, target, visited, [...path, start]);
if (newPath) return newPath;
}
return null;
}
function findPathFromLinkId(linkId) {
const startNodeIndex = data.links.findIndex(link => link.id === linkId);
if (startNodeIndex === -1) {
return null;
}
const adjList = buildReversedAdjacencyList(data.nodes, data.links);
const visited = Array(data.nodes.length).fill(false);
return dfs(adjList, startNodeIndex, 0, visited, []);
}
const handleLinkMouseEnter = (linkData: any) => {
const { payload } = linkData;
const fullPathArray: Node[] = [];
console.log('linkData', linkData.index);
// Add the source node of the current link
fullPathArray.push(payload.source);
fullPathArray.push(payload.target);
const pathFromLinkId = findPathFromLinkId(payload.id);
setHoveredLinks(pathFromLinkId);
if (payload.source.sourceLinks.length > 0) {
let prevLink = data.links[payload.source.sourceLinks[0]];
// fullPathArray.unshift(prevLink);
fullPathArray.unshift(data.nodes[prevLink.source]);
};
if (prevLink.source) {
let prevLinkPrev = data.links[prevLink.source];
// fullPathArray.unshift(prevLinkPrev);
fullPathArray.unshift(data.nodes[prevLinkPrev.source]);
}
const clickHandler = () => {
setHighlightedLinks(hoveredLinks);
const targetLink = data.links[hoveredLinks[0]];
const sourceLink = data.links[hoveredLinks[hoveredLinks.length - 1]];
const targetNode = data.nodes[targetLink.source];
const sourceNode = data.nodes[sourceLink.target];
const filters = [];
if (sourceNode) {
filters.push({
operator: 'is',
type: sourceNode.eventType,
value: [sourceNode.name],
isEvent: true
});
}
setHighlightedLinks(fullPathArray);
if (targetNode) {
filters.push({
operator: 'is',
type: targetNode.eventType,
value: [targetNode.name],
isEvent: true
});
}
console.log('fullPathArray', fullPathArray.map(node => node));
onChartClick?.(filters);
};
@ -76,15 +127,15 @@ const SankeyChart: React.FC<Props> = ({
iterations={128}
node={<CustomNode />}
sort={true}
onClick={(data) => {
}}
onClick={clickHandler}
link={({ source, target, ...linkProps }, index) => (
<CustomLink
{...linkProps}
hoveredLinks={hoveredLinks.map(linkId => data.links[linkId].id)}
activeLinks={highlightedLinks.map(linkId => data.links[linkId].id)}
strokeOpacity={highlightedLinks.includes(index) ? 1 : 0.2}
onMouseEnter={() => handleLinkMouseEnter(linkProps)}
onMouseLeave={() => setHighlightedLinks([])}
onMouseLeave={() => setHoveredLinks([])}
/>
)}
margin={{ right: 200 }}

View file

@ -261,8 +261,13 @@ export default class Widget {
const _data: any = { ...data };
if (this.metricType === USER_PATH) {
_data['nodes'] = data.nodes.map((s: any) => ({
...s,
idd: Math.random().toString(36).substring(7),
}));
_data['links'] = data.links.map((s: any) => ({
...s
...s,
id: Math.random().toString(36).substring(7),
// value: Math.round(s.value),
}));