Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 38 additions & 8 deletions src/components/lineage/converters/getGraphEdges.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
IndirectColumnLineageRelationLineageResponseV1,
LineageResponseV1,
RelationEndpointLineageResponseV1,
AncestorRelationLineageResponseV1,
} from "@/dataProvider/types";
import { Edge, MarkerType } from "@xyflow/react";
import { getDatasetIdToRelatedDatasetIdsMapping } from "./getGraphNodes";
Expand All @@ -29,7 +30,9 @@ const getMinimalEdge = (relation: BaseRelationLineageResponseV1): Edge => {
return {
id: getEdgeId(relation),
source: getNodeId(relation.from),
sourceHandle: "right",
target: getNodeId(relation.to),
targetHandle: "left",
type: "baseEdge",
markerEnd: {
type: MarkerType.ArrowClosed,
Expand Down Expand Up @@ -63,8 +66,8 @@ const getOutputEdge = (
datasetIdToContainerIdMapping: Map<string, string>,
rawResponse: LineageResponseV1,
): Edge => {
let source: string = getNodeId(relation.from);
let sourceHandle: string | null = null;
let source = getNodeId(relation.from);
let sourceHandle = "right";
let strokeWidth = STOKE_THICK;

if (relation.from.kind == "DATASET") {
Expand Down Expand Up @@ -110,7 +113,7 @@ const getOutputEdge = (
const containerTo = datasetIdToContainerIdMapping.get(relation.to.id)!;
return {
...getMinimalEdge(relation),
id: `${source}:${sourceHandle ?? "*"}->${getNodeId(relation.to)}`,
id: `${source}:${sourceHandle}->${getNodeId(relation.to)}`,
source: source,
sourceHandle: sourceHandle,
target: containerTo,
Expand Down Expand Up @@ -140,8 +143,8 @@ const getInputEdge = (
datasetIdToContainerIdMapping: Map<string, string>,
rawResponse: LineageResponseV1,
): Edge => {
let target: string = getNodeId(relation.to);
let targetHandle: string | null = null;
let target = getNodeId(relation.to);
let targetHandle = "left";
let strokeWidth = STOKE_THICK;

if (relation.to.kind == "OPERATION") {
Expand Down Expand Up @@ -184,7 +187,7 @@ const getInputEdge = (
const containerFrom = datasetIdToContainerIdMapping.get(relation.from.id)!;
return {
...getMinimalEdge(relation),
id: `${getNodeId(relation.from)}->${target}:${targetHandle ?? "*"}`,
id: `${getNodeId(relation.from)}->${target}:${targetHandle}`,
source: containerFrom,
sourceHandle: getNodeId(relation.from),
target: target,
Expand Down Expand Up @@ -226,7 +229,7 @@ const getColumnLineageEdge = (
source: containerFrom,
sourceHandle: sourceFieldName,
target: containerTo,
targetHandle: targetFieldName,
targetHandle: targetFieldName ?? "left",
type: "columnLineageEdge",
data: {
source_field: sourceFieldName,
Expand Down Expand Up @@ -315,6 +318,26 @@ const mergeColumnLineageEdges = (edges: Edge[]): Edge[] => {
return Array.from(grouped.values());
};

const getAncestorEdges = (
relation: AncestorRelationLineageResponseV1,
): Edge[] => {
if (relation.from.kind != "JOB" && relation.to.kind != "JOB") {
return [];
}

return [
{
...getMinimalEdge(relation),
source: getNodeId(relation.from),
sourceHandle: "bottom",
target: getNodeId(relation.to),
targetHandle: "top",
type: "ancestorEdge",
label: "ANCESTOR",
},
];
};

const getGraphEdges = (rawResponse: LineageResponseV1): Edge[] => {
const datasetIdToContainerIdMapping: Map<string, string> = new Map();
getDatasetIdToRelatedDatasetIdsMapping(rawResponse).forEach(
Expand All @@ -326,6 +349,9 @@ const getGraphEdges = (rawResponse: LineageResponseV1): Edge[] => {
},
);

const ancestorEdges: Edge[] =
rawResponse.relations.ancestors.flatMap(getAncestorEdges);

const ioEdges: Edge[] = [
...rawResponse.relations.inputs.map((relation) =>
getInputEdge(relation, datasetIdToContainerIdMapping, rawResponse),
Expand All @@ -350,7 +376,11 @@ const getGraphEdges = (rawResponse: LineageResponseV1): Edge[] => {
),
];

return [...ioEdges, ...mergeColumnLineageEdges(columnLineage)];
return [
...ancestorEdges,
...ioEdges,
...mergeColumnLineageEdges(columnLineage),
];
};

export default getGraphEdges;
34 changes: 28 additions & 6 deletions src/components/lineage/nodes/base_node/BaseNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,17 @@ const BaseNode = ({
const { getEdges } = useReactFlow();
const updateNodeInternals = useUpdateNodeInternals();

const hasOutgoing = getEdges().some(
(edge) => edge.source === nodeId && !edge.sourceHandle,
const hasAncestors = getEdges().some(
(edge) => edge.target === nodeId && edge.sourceHandle == "bottom",
);
const hasIncoming = getEdges().some(
(edge) => edge.target === nodeId && !edge.targetHandle,
const hasDescendants = getEdges().some(
(edge) => edge.source === nodeId && edge.targetHandle == "top",
);
const hasOutputs = getEdges().some(
(edge) => edge.source === nodeId && edge.sourceHandle == "right",
);
const hasInputs = getEdges().some(
(edge) => edge.target === nodeId && edge.targetHandle == "left",
);

const [expanded, setExpanded] = useState(defaultExpanded);
Expand All @@ -54,8 +60,16 @@ const BaseNode = ({

return (
<Card {...props}>
{hasAncestors && (
<Handle
type="target"
id="top"
position={Position.Top}
isConnectable={false}
/>
)}
<Stack direction={"row"} sx={{ alignItems: "center" }}>
{hasIncoming && (
{hasInputs && (
<Handle
type="target"
id="left"
Expand All @@ -76,7 +90,7 @@ const BaseNode = ({
/>
</CardActions>
)}
{hasOutgoing && (
{hasOutputs && (
<Handle
type="source"
id="right"
Expand All @@ -90,6 +104,14 @@ const BaseNode = ({
<CardContent>{expandableContent}</CardContent>
</Collapse>
)}
{hasDescendants && (
<Handle
type="source"
id="bottom"
position={Position.Bottom}
isConnectable={false}
/>
)}
</Card>
);
};
Expand Down
5 changes: 5 additions & 0 deletions src/dataProvider/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,9 @@ interface OutputRelationLineageResponseV1 extends BaseRelationLineageResponseV1
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
interface ParentRelationLineageResponseV1 extends BaseRelationLineageResponseV1 {}

// eslint-disable-next-line @typescript-eslint/no-empty-object-type
interface AncestorRelationLineageResponseV1 extends BaseRelationLineageResponseV1 {}

type SymlinkRelationTypeLineageResponseV1 = "METASTORE" | "WAREHOUSE";

type ColumnLineageTransformationTypeLineageResponseV1 =
Expand Down Expand Up @@ -257,6 +260,7 @@ interface SymlinkRelationLineageResponseV1 extends BaseRelationLineageResponseV1

interface LineageRelationsResponseV1 {
parents: ParentRelationLineageResponseV1[];
ancestors: AncestorRelationLineageResponseV1[];
inputs: InputRelationLineageResponseV1[];
outputs: OutputRelationLineageResponseV1[];
symlinks: SymlinkRelationLineageResponseV1[];
Expand Down Expand Up @@ -324,6 +328,7 @@ export type {
EntityTypeLineageResponseV1,
RelationEndpointLineageResponseV1,
BaseRelationLineageResponseV1,
AncestorRelationLineageResponseV1,
InputRelationLineageResponseV1,
IORelationSchemaFieldV1,
IORelationSchemaRelevanceTypeV1,
Expand Down
Loading