2021-10-22 15:46:46 -07:00
|
|
|
import React from 'react';
|
2021-04-03 11:13:25 -07:00
|
|
|
import { Group } from '@vx/group';
|
2021-10-22 15:46:46 -07:00
|
|
|
import { curveBasis } from '@vx/curve';
|
|
|
|
import { LinePath } from '@vx/shape';
|
2021-04-06 18:21:33 -07:00
|
|
|
import { TransformMatrix } from '@vx/zoom/lib/types';
|
2021-04-03 11:13:25 -07:00
|
|
|
|
2022-05-23 17:21:30 -04:00
|
|
|
import { NodeData, Direction, EntitySelectParams, TreeProps, VizNode, VizEdge, EntityAndType } from './types';
|
2021-04-03 11:13:25 -07:00
|
|
|
import LineageEntityNode from './LineageEntityNode';
|
2021-08-31 22:00:56 -07:00
|
|
|
import { ANTD_GRAY } from '../entity/shared/constants';
|
2021-04-03 11:13:25 -07:00
|
|
|
|
|
|
|
type Props = {
|
2021-10-22 15:46:46 -07:00
|
|
|
data: NodeData;
|
2021-04-03 11:13:25 -07:00
|
|
|
zoom: {
|
2021-04-06 18:21:33 -07:00
|
|
|
transformMatrix: TransformMatrix;
|
2021-04-03 11:13:25 -07:00
|
|
|
};
|
|
|
|
onEntityClick: (EntitySelectParams) => void;
|
2021-04-23 00:18:39 -07:00
|
|
|
onEntityCenter: (EntitySelectParams) => void;
|
2022-05-23 17:21:30 -04:00
|
|
|
onLineageExpand: (data: EntityAndType) => void;
|
2021-04-03 11:13:25 -07:00
|
|
|
selectedEntity?: EntitySelectParams;
|
2021-10-22 15:46:46 -07:00
|
|
|
hoveredEntity?: EntitySelectParams;
|
|
|
|
setHoveredEntity: (EntitySelectParams) => void;
|
|
|
|
onDrag: (params: EntitySelectParams, event: React.MouseEvent) => void;
|
2021-04-03 11:13:25 -07:00
|
|
|
margin: TreeProps['margin'];
|
|
|
|
direction: Direction;
|
2021-10-22 15:46:46 -07:00
|
|
|
nodesToRender: VizNode[];
|
|
|
|
edgesToRender: VizEdge[];
|
|
|
|
nodesByUrn: Record<string, VizNode>;
|
2021-04-03 11:13:25 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
function transformToString(transform: {
|
|
|
|
scaleX: number;
|
|
|
|
scaleY: number;
|
|
|
|
translateX: number;
|
|
|
|
translateY: number;
|
|
|
|
skewX: number;
|
|
|
|
skewY: number;
|
|
|
|
}): string {
|
|
|
|
return `matrix(${transform.scaleX}, ${transform.skewX}, ${transform.skewY}, ${transform.scaleY}, ${transform.translateX}, ${transform.translateY})`;
|
|
|
|
}
|
|
|
|
|
|
|
|
export default function LineageTreeNodeAndEdgeRenderer({
|
2021-10-22 15:46:46 -07:00
|
|
|
data,
|
2021-04-03 11:13:25 -07:00
|
|
|
zoom,
|
|
|
|
margin,
|
|
|
|
onEntityClick,
|
2021-04-23 00:18:39 -07:00
|
|
|
onEntityCenter,
|
2021-04-03 11:13:25 -07:00
|
|
|
onLineageExpand,
|
|
|
|
selectedEntity,
|
2021-10-22 15:46:46 -07:00
|
|
|
hoveredEntity,
|
|
|
|
setHoveredEntity,
|
|
|
|
onDrag,
|
2021-04-03 11:13:25 -07:00
|
|
|
direction,
|
2021-10-22 15:46:46 -07:00
|
|
|
nodesToRender,
|
|
|
|
edgesToRender,
|
|
|
|
nodesByUrn,
|
2021-04-03 11:13:25 -07:00
|
|
|
}: Props) {
|
2021-10-22 15:46:46 -07:00
|
|
|
const isLinkHighlighted = (link) =>
|
|
|
|
link.source.data.urn === hoveredEntity?.urn || link.target.data.urn === hoveredEntity?.urn;
|
2021-04-03 11:13:25 -07:00
|
|
|
return (
|
2021-10-22 15:46:46 -07:00
|
|
|
<Group transform={transformToString(zoom.transformMatrix)} top={margin?.top} left={margin?.left}>
|
|
|
|
{[
|
|
|
|
// we want to render non-highlighted links first since svg does not support the
|
|
|
|
// concept of a z-index
|
|
|
|
...edgesToRender.filter((link) => !isLinkHighlighted(link)),
|
|
|
|
...edgesToRender.filter(isLinkHighlighted),
|
|
|
|
].map((link) => {
|
|
|
|
const isHighlighted = isLinkHighlighted(link);
|
|
|
|
|
2021-04-03 11:13:25 -07:00
|
|
|
return (
|
2021-10-22 15:46:46 -07:00
|
|
|
<Group key={`edge-${link.source.data.urn}-${link.target.data.urn}-${direction}`}>
|
|
|
|
<LinePath
|
|
|
|
// we rotated the svg 90 degrees so we need to switch x & y for the last mile
|
|
|
|
x={(d) => d.y}
|
|
|
|
y={(d) => d.x}
|
|
|
|
curve={curveBasis}
|
|
|
|
data={link.curve}
|
|
|
|
stroke={isHighlighted ? '#1890FF' : ANTD_GRAY[6]}
|
|
|
|
strokeWidth="1"
|
|
|
|
markerEnd={`url(#triangle-downstream${isHighlighted ? '-highlighted' : ''})`}
|
|
|
|
markerStart={`url(#triangle-upstream${isHighlighted ? '-highlighted' : ''})`}
|
|
|
|
data-testid={`edge-${link.source.data.urn}-${link.target.data.urn}-${direction}`}
|
|
|
|
/>
|
|
|
|
</Group>
|
2021-04-03 11:13:25 -07:00
|
|
|
);
|
|
|
|
})}
|
|
|
|
{nodesToRender.map((node) => {
|
|
|
|
const isSelected = node.data.urn === selectedEntity?.urn;
|
|
|
|
const isHovered = node.data.urn === hoveredEntity?.urn;
|
2021-10-22 15:46:46 -07:00
|
|
|
|
2021-04-03 11:13:25 -07:00
|
|
|
return (
|
|
|
|
<LineageEntityNode
|
|
|
|
key={`node-${node.data.urn}-${direction}`}
|
|
|
|
node={node}
|
|
|
|
isSelected={isSelected}
|
|
|
|
isHovered={isHovered}
|
|
|
|
onHover={(select: EntitySelectParams) => setHoveredEntity(select)}
|
|
|
|
onEntityClick={onEntityClick}
|
2021-04-23 00:18:39 -07:00
|
|
|
onEntityCenter={onEntityCenter}
|
2021-04-03 11:13:25 -07:00
|
|
|
onExpandClick={onLineageExpand}
|
|
|
|
direction={direction}
|
2021-10-22 15:46:46 -07:00
|
|
|
isCenterNode={data.urn === node.data.urn}
|
2021-04-05 19:23:07 -07:00
|
|
|
nodesToRenderByUrn={nodesByUrn}
|
2021-10-22 15:46:46 -07:00
|
|
|
onDrag={onDrag}
|
2021-04-03 11:13:25 -07:00
|
|
|
/>
|
|
|
|
);
|
|
|
|
})}
|
|
|
|
</Group>
|
|
|
|
);
|
|
|
|
}
|