This is an automated email from the ASF dual-hosted git repository.
phanikumv pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new 84dcfe7eb2 Add dataset event info to dag graph (#41012)
84dcfe7eb2 is described below
commit 84dcfe7eb2c3862f543a350db0f1212ea17dc3db
Author: Brent Bovenzi <[email protected]>
AuthorDate: Fri Jul 26 02:38:28 2024 -0400
Add dataset event info to dag graph (#41012)
---
airflow/www/static/js/api/useDatasetEvents.ts | 27 +++++--
airflow/www/static/js/api/useTaskInstance.ts | 4 +-
.../www/static/js/api/useUpstreamDatasetEvents.ts | 42 +++++-----
.../www/static/js/components/DatasetEventCard.tsx | 51 +-----------
.../static/js/components/SourceTaskInstance.tsx | 16 ++--
.../www/static/js/components/TriggeredDagRuns.tsx | 91 ++++++++++++++++++++++
.../js/dag/details/dagRun/DatasetTriggerEvents.tsx | 5 +-
.../static/js/dag/details/graph/DatasetNode.tsx | 86 +++++++++++++++-----
airflow/www/static/js/dag/details/graph/Node.tsx | 2 +
airflow/www/static/js/dag/details/graph/index.tsx | 39 ++++++++--
airflow/www/static/js/dag/details/graph/utils.ts | 7 ++
11 files changed, 262 insertions(+), 108 deletions(-)
diff --git a/airflow/www/static/js/api/useDatasetEvents.ts
b/airflow/www/static/js/api/useDatasetEvents.ts
index 8caccd202c..30e4670a87 100644
--- a/airflow/www/static/js/api/useDatasetEvents.ts
+++ b/airflow/www/static/js/api/useDatasetEvents.ts
@@ -17,14 +17,21 @@
* under the License.
*/
-import axios, { AxiosResponse } from "axios";
-import { useQuery } from "react-query";
+import axios from "axios";
+import { useQuery, UseQueryOptions } from "react-query";
import { getMetaValue } from "src/utils";
-import type { API } from "src/types";
import URLSearchParamsWrapper from "src/utils/URLSearchParamWrapper";
+import type {
+ DatasetEventCollection,
+ GetDatasetEventsVariables,
+} from "src/types/api-generated";
-export default function useDatasetEvents({
+interface Props extends GetDatasetEventsVariables {
+ options?: UseQueryOptions<DatasetEventCollection>;
+}
+
+const useDatasetEvents = ({
datasetId,
sourceDagId,
sourceRunId,
@@ -33,8 +40,9 @@ export default function useDatasetEvents({
limit,
offset,
orderBy,
-}: API.GetDatasetEventsVariables) {
- const query = useQuery(
+ options,
+}: Props) => {
+ const query = useQuery<DatasetEventCollection>(
[
"datasets-events",
datasetId,
@@ -61,16 +69,19 @@ export default function useDatasetEvents({
if (sourceMapIndex)
params.set("source_map_index", sourceMapIndex.toString());
- return axios.get<AxiosResponse, API.DatasetEventCollection>(datasetsUrl,
{
+ return axios.get(datasetsUrl, {
params,
});
},
{
keepPreviousData: true,
+ ...options,
}
);
return {
...query,
data: query.data ?? { datasetEvents: [], totalEntries: 0 },
};
-}
+};
+
+export default useDatasetEvents;
diff --git a/airflow/www/static/js/api/useTaskInstance.ts
b/airflow/www/static/js/api/useTaskInstance.ts
index 8e7c4faf32..c5a96f3e44 100644
--- a/airflow/www/static/js/api/useTaskInstance.ts
+++ b/airflow/www/static/js/api/useTaskInstance.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import axios, { AxiosResponse } from "axios";
+import axios from "axios";
import type { API } from "src/types";
import { useQuery, UseQueryOptions } from "react-query";
import { useAutoRefresh } from "src/context/autorefresh";
@@ -55,7 +55,7 @@ const useTaskInstance = ({
return useQuery<API.TaskInstance>(
["taskInstance", dagId, dagRunId, taskId, mapIndex],
- () => axios.get<AxiosResponse, API.TaskInstance>(url),
+ () => axios.get(url),
{
refetchInterval: isRefreshOn && (autoRefreshInterval || 1) * 1000,
...options,
diff --git a/airflow/www/static/js/api/useUpstreamDatasetEvents.ts
b/airflow/www/static/js/api/useUpstreamDatasetEvents.ts
index 5ba492183c..32d1c7aeff 100644
--- a/airflow/www/static/js/api/useUpstreamDatasetEvents.ts
+++ b/airflow/www/static/js/api/useUpstreamDatasetEvents.ts
@@ -17,29 +17,35 @@
* under the License.
*/
-import axios, { AxiosResponse } from "axios";
-import { useQuery } from "react-query";
+import axios from "axios";
+import { useQuery, UseQueryOptions } from "react-query";
import { getMetaValue } from "src/utils";
-import type { API } from "src/types";
+import type {
+ DatasetEventCollection,
+ GetUpstreamDatasetEventsVariables,
+} from "src/types/api-generated";
-interface Props {
- runId: string;
+interface Props extends GetUpstreamDatasetEventsVariables {
+ options?: UseQueryOptions<DatasetEventCollection>;
}
-export default function useUpstreamDatasetEvents({ runId }: Props) {
- const query = useQuery(["upstreamDatasetEvents", runId], () => {
- const dagId = getMetaValue("dag_id");
- const upstreamEventsUrl = (
- getMetaValue("upstream_dataset_events_api") ||
- `api/v1/dags/${dagId}/dagRuns/_DAG_RUN_ID_/upstreamDatasetEvents`
- ).replace("_DAG_RUN_ID_", encodeURIComponent(runId));
- return axios.get<AxiosResponse, API.DatasetEventCollection>(
- upstreamEventsUrl
- );
- });
+const useUpstreamDatasetEvents = ({ dagId, dagRunId, options }: Props) => {
+ const upstreamEventsUrl = (
+ getMetaValue("upstream_dataset_events_api") ||
+ `api/v1/dags/${dagId}/dagRuns/_DAG_RUN_ID_/upstreamDatasetEvents`
+ ).replace("_DAG_RUN_ID_", encodeURIComponent(dagRunId));
+
+ const query = useQuery<DatasetEventCollection>(
+ ["upstreamDatasetEvents", dagRunId],
+ () => axios.get(upstreamEventsUrl),
+ options
+ );
+
return {
...query,
- data: query.data || { datasetEvents: [], totalEntries: 0 },
+ data: query.data ?? { datasetEvents: [], totalEntries: 0 },
};
-}
+};
+
+export default useUpstreamDatasetEvents;
diff --git a/airflow/www/static/js/components/DatasetEventCard.tsx
b/airflow/www/static/js/components/DatasetEventCard.tsx
index e6c5b6bb9c..ee00def48d 100644
--- a/airflow/www/static/js/components/DatasetEventCard.tsx
+++ b/airflow/www/static/js/components/DatasetEventCard.tsx
@@ -32,23 +32,20 @@ import {
Link,
} from "@chakra-ui/react";
import { HiDatabase } from "react-icons/hi";
-import { FiLink } from "react-icons/fi";
import { useSearchParams } from "react-router-dom";
import { getMetaValue } from "src/utils";
import Time from "src/components/Time";
import { useContainerRef } from "src/context/containerRef";
-import { SimpleStatus } from "src/dag/StatusBox";
-import { formatDuration, getDuration } from "src/datetime_utils";
import RenderedJsonField from "src/components/RenderedJsonField";
import SourceTaskInstance from "./SourceTaskInstance";
+import TriggeredDagRuns from "./TriggeredDagRuns";
type CardProps = {
datasetEvent: DatasetEvent;
};
-const gridUrl = getMetaValue("grid_url");
const datasetsUrl = getMetaValue("datasets_url");
const DatasetEventCard = ({ datasetEvent }: CardProps) => {
@@ -116,51 +113,7 @@ const DatasetEventCard = ({ datasetEvent }: CardProps) => {
{!!datasetEvent?.createdDagruns?.length && (
<>
Triggered Dag Runs:
- <Flex alignItems="center">
- {datasetEvent?.createdDagruns.map((run) => {
- const runId = (run as any).dagRunId; // For some reason the
type is wrong here
- const url = `${gridUrl?.replace(
- "__DAG_ID__",
- run.dagId || ""
- )}?dag_run_id=${encodeURIComponent(runId)}`;
-
- return (
- <Tooltip
- key={runId}
- label={
- <Box>
- <Text>DAG Id: {run.dagId}</Text>
- <Text>Status: {run.state || "no status"}</Text>
- <Text>
- Duration:{" "}
- {formatDuration(
- getDuration(run.startDate, run.endDate)
- )}
- </Text>
- <Text>
- Start Date: <Time dateTime={run.startDate} />
- </Text>
- {run.endDate && (
- <Text>
- End Date: <Time dateTime={run.endDate} />
- </Text>
- )}
- </Box>
- }
- portalProps={{ containerRef }}
- hasArrow
- placement="top"
- >
- <Flex width="30px">
- <SimpleStatus state={run.state} mx={1} />
- <Link color="blue.600" href={url}>
- <FiLink size="12px" />
- </Link>
- </Flex>
- </Tooltip>
- );
- })}
- </Flex>
+ <TriggeredDagRuns createdDagRuns={datasetEvent?.createdDagruns}
/>
</>
)}
</GridItem>
diff --git a/airflow/www/static/js/components/SourceTaskInstance.tsx
b/airflow/www/static/js/components/SourceTaskInstance.tsx
index 3dcae30d32..e2db366c29 100644
--- a/airflow/www/static/js/components/SourceTaskInstance.tsx
+++ b/airflow/www/static/js/components/SourceTaskInstance.tsx
@@ -31,11 +31,15 @@ import { getMetaValue } from "src/utils";
type SourceTIProps = {
datasetEvent: DatasetEvent;
+ showLink?: boolean;
};
const gridUrl = getMetaValue("grid_url");
-const SourceTaskInstance = ({ datasetEvent }: SourceTIProps) => {
+const SourceTaskInstance = ({
+ datasetEvent,
+ showLink = true,
+}: SourceTIProps) => {
const containerRef = useContainerRef();
const { sourceDagId, sourceRunId, sourceTaskId, sourceMapIndex } =
datasetEvent;
@@ -80,11 +84,13 @@ const SourceTaskInstance = ({ datasetEvent }:
SourceTIProps) => {
hasArrow
placement="top"
>
- <Flex width="30px">
+ <Flex width={showLink ? "30px" : "16px"}>
<SimpleStatus state={taskInstance.state} mx={1} />
- <Link color="blue.600" href={url}>
- <FiLink size="12px" />
- </Link>
+ {showLink && (
+ <Link color="blue.600" href={url}>
+ <FiLink size="12px" />
+ </Link>
+ )}
</Flex>
</Tooltip>
)}
diff --git a/airflow/www/static/js/components/TriggeredDagRuns.tsx
b/airflow/www/static/js/components/TriggeredDagRuns.tsx
new file mode 100644
index 0000000000..f017fbe488
--- /dev/null
+++ b/airflow/www/static/js/components/TriggeredDagRuns.tsx
@@ -0,0 +1,91 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React from "react";
+
+import type { DAGRun } from "src/types/api-generated";
+import { Box, Flex, Tooltip, Text, Link } from "@chakra-ui/react";
+import { FiLink } from "react-icons/fi";
+
+import { getMetaValue } from "src/utils";
+import Time from "src/components/Time";
+import { useContainerRef } from "src/context/containerRef";
+import { SimpleStatus } from "src/dag/StatusBox";
+import { formatDuration, getDuration } from "src/datetime_utils";
+
+type CardProps = {
+ createdDagRuns: DAGRun[];
+ showLink?: boolean;
+};
+
+const gridUrl = getMetaValue("grid_url");
+
+const TriggeredDagRuns = ({ createdDagRuns, showLink = true }: CardProps) => {
+ const containerRef = useContainerRef();
+
+ return (
+ <Flex alignItems="center">
+ {createdDagRuns.map((run) => {
+ const runId = (run as any).dagRunId; // For some reason the type is
wrong here
+ const url = `${gridUrl?.replace(
+ "__DAG_ID__",
+ run.dagId || ""
+ )}?dag_run_id=${encodeURIComponent(runId)}`;
+
+ return (
+ <Tooltip
+ key={runId}
+ label={
+ <Box>
+ <Text>DAG Id: {run.dagId}</Text>
+ <Text>Status: {run.state || "no status"}</Text>
+ <Text>
+ Duration:{" "}
+ {formatDuration(getDuration(run.startDate, run.endDate))}
+ </Text>
+ <Text>
+ Start Date: <Time dateTime={run.startDate} />
+ </Text>
+ {run.endDate && (
+ <Text>
+ End Date: <Time dateTime={run.endDate} />
+ </Text>
+ )}
+ </Box>
+ }
+ portalProps={{ containerRef }}
+ hasArrow
+ placement="top"
+ >
+ <Flex width={showLink ? "30px" : "16px"}>
+ <SimpleStatus state={run.state} mx={1} />
+ {showLink && (
+ <Link color="blue.600" href={url}>
+ <FiLink size="12px" />
+ </Link>
+ )}
+ </Flex>
+ </Tooltip>
+ );
+ })}
+ </Flex>
+ );
+};
+
+export default TriggeredDagRuns;
diff --git a/airflow/www/static/js/dag/details/dagRun/DatasetTriggerEvents.tsx
b/airflow/www/static/js/dag/details/dagRun/DatasetTriggerEvents.tsx
index 3a3ec3eb69..b9d0c1c169 100644
--- a/airflow/www/static/js/dag/details/dagRun/DatasetTriggerEvents.tsx
+++ b/airflow/www/static/js/dag/details/dagRun/DatasetTriggerEvents.tsx
@@ -24,11 +24,14 @@ import type { DagRun as DagRunType } from "src/types";
import { CardDef, CardList } from "src/components/Table";
import type { DatasetEvent } from "src/types/api-generated";
import DatasetEventCard from "src/components/DatasetEventCard";
+import { getMetaValue } from "src/utils";
interface Props {
runId: DagRunType["runId"];
}
+const dagId = getMetaValue("dag_id");
+
const cardDef: CardDef<DatasetEvent> = {
card: ({ row }) => <DatasetEventCard datasetEvent={row} />,
};
@@ -37,7 +40,7 @@ const DatasetTriggerEvents = ({ runId }: Props) => {
const {
data: { datasetEvents = [] },
isLoading,
- } = useUpstreamDatasetEvents({ runId });
+ } = useUpstreamDatasetEvents({ dagRunId: runId, dagId });
const columns = useMemo(
() => [
diff --git a/airflow/www/static/js/dag/details/graph/DatasetNode.tsx
b/airflow/www/static/js/dag/details/graph/DatasetNode.tsx
index 921341643b..8c1692513c 100644
--- a/airflow/www/static/js/dag/details/graph/DatasetNode.tsx
+++ b/airflow/www/static/js/dag/details/graph/DatasetNode.tsx
@@ -26,6 +26,7 @@ import {
PopoverBody,
PopoverCloseButton,
PopoverContent,
+ PopoverFooter,
PopoverHeader,
PopoverTrigger,
Portal,
@@ -33,18 +34,25 @@ import {
} from "@chakra-ui/react";
import { HiDatabase } from "react-icons/hi";
import type { NodeProps } from "reactflow";
+import { TbApi } from "react-icons/tb";
import { getMetaValue } from "src/utils";
import { useContainerRef } from "src/context/containerRef";
+import Time from "src/components/Time";
+import SourceTaskInstance from "src/components/SourceTaskInstance";
+import TriggeredDagRuns from "src/components/TriggeredDagRuns";
+
import type { CustomNodeProps } from "./Node";
const datasetsUrl = getMetaValue("datasets_url");
const DatasetNode = ({
- data: { label, height, width, latestDagRunId, isZoomedOut },
+ data: { label, height, width, latestDagRunId, isZoomedOut, datasetEvent },
}: NodeProps<CustomNodeProps>) => {
const containerRef = useContainerRef();
+ const { fromRestApi } = (datasetEvent?.extra || {}) as Record<string,
string>;
+
return (
<Popover>
<PopoverTrigger>
@@ -70,23 +78,37 @@ const DatasetNode = ({
{label}
</Text>
{!isZoomedOut && (
- <Text
- maxWidth={`calc(${width}px - 12px)`}
- fontWeight={400}
- fontSize="md"
- textAlign="justify"
- color="gray.500"
- >
- <HiDatabase
- size="16px"
- style={{
- display: "inline",
- verticalAlign: "middle",
- marginRight: "3px",
- }}
- />
- Dataset
- </Text>
+ <>
+ <Text
+ maxWidth={`calc(${width}px - 12px)`}
+ fontWeight={400}
+ fontSize="md"
+ textAlign="justify"
+ color="gray.500"
+ >
+ <HiDatabase
+ size="16px"
+ style={{
+ display: "inline",
+ verticalAlign: "middle",
+ marginRight: "3px",
+ }}
+ />
+ Dataset
+ </Text>
+ {!!datasetEvent && (
+ <Text
+ fontWeight={400}
+ fontSize="md"
+ textAlign="justify"
+ color="gray.500"
+ alignSelf="flex-end"
+ >
+ {/* @ts-ignore */}
+ {moment(datasetEvent.timestamp).fromNow()}
+ </Text>
+ )}
+ </>
)}
</Box>
</PopoverTrigger>
@@ -95,14 +117,38 @@ const DatasetNode = ({
<PopoverArrow bg="gray.100" />
<PopoverCloseButton />
<PopoverHeader>{label}</PopoverHeader>
- <PopoverBody>
+ {!!datasetEvent && (
+ <PopoverBody>
+ <Time dateTime={datasetEvent?.timestamp} />
+ <Box>
+ Source:
+ {fromRestApi && <TbApi size="20px" />}
+ {!!datasetEvent?.sourceTaskId && (
+ <SourceTaskInstance
+ datasetEvent={datasetEvent}
+ showLink={false}
+ />
+ )}
+ {!!datasetEvent?.createdDagruns?.length && (
+ <>
+ Triggered Dag Runs:
+ <TriggeredDagRuns
+ createdDagRuns={datasetEvent?.createdDagruns}
+ showLink={false}
+ />
+ </>
+ )}
+ </Box>
+ </PopoverBody>
+ )}
+ <PopoverFooter>
<Link
color="blue"
href={`${datasetsUrl}?uri=${encodeURIComponent(label)}`}
>
View Dataset
</Link>
- </PopoverBody>
+ </PopoverFooter>
</PopoverContent>
</Portal>
</Popover>
diff --git a/airflow/www/static/js/dag/details/graph/Node.tsx
b/airflow/www/static/js/dag/details/graph/Node.tsx
index 04f1d56fa0..896f59f786 100644
--- a/airflow/www/static/js/dag/details/graph/Node.tsx
+++ b/airflow/www/static/js/dag/details/graph/Node.tsx
@@ -22,6 +22,7 @@ import { Box } from "@chakra-ui/react";
import { Handle, NodeProps, Position } from "reactflow";
import type { DepNode, DagRun, Task, TaskInstance } from "src/types";
+import type { DatasetEvent } from "src/types/api-generated";
import DagNode from "./DagNode";
import DatasetNode from "./DatasetNode";
@@ -44,6 +45,7 @@ export interface CustomNodeProps {
style?: string;
isZoomedOut: boolean;
class: DepNode["value"]["class"];
+ datasetEvent?: DatasetEvent;
}
const Node = (props: NodeProps<CustomNodeProps>) => {
diff --git a/airflow/www/static/js/dag/details/graph/index.tsx
b/airflow/www/static/js/dag/details/graph/index.tsx
index f558f1734e..ea312f4e83 100644
--- a/airflow/www/static/js/dag/details/graph/index.tsx
+++ b/airflow/www/static/js/dag/details/graph/index.tsx
@@ -30,7 +30,13 @@ import ReactFlow, {
Viewport,
} from "reactflow";
-import { useDatasets, useGraphData, useGridData } from "src/api";
+import {
+ useDatasetEvents,
+ useDatasets,
+ useGraphData,
+ useGridData,
+ useUpstreamDatasetEvents,
+} from "src/api";
import useSelection from "src/dag/useSelection";
import { getMetaValue, getTask, useOffsetTop } from "src/utils";
import { useGraphLayout } from "src/utils/graph";
@@ -57,6 +63,7 @@ const Graph = ({ openGroupIds, onToggleGroups,
hoveredTaskState }: Props) => {
const [arrange, setArrange] = useState(data?.arrange || "LR");
const [hasRendered, setHasRendered] = useState(false);
const [isZoomedOut, setIsZoomedOut] = useState(false);
+ const { selected } = useSelection();
const {
data: { dagRuns, groups },
@@ -70,6 +77,27 @@ const Graph = ({ openGroupIds, onToggleGroups,
hoveredTaskState }: Props) => {
dagIds: [dagId],
});
+ const enabledDatasets = !!(
+ selected.runId && datasetsCollection?.datasets?.length
+ );
+
+ const {
+ data: { datasetEvents: upstreamDatasetEvents = [] },
+ } = useUpstreamDatasetEvents({
+ dagId,
+ dagRunId: selected.runId || "",
+ options: { enabled: enabledDatasets },
+ });
+
+ const {
+ data: { datasetEvents: downstreamDatasetEvents = [] },
+ } = useDatasetEvents({
+ sourceDagId: dagId,
+ sourceRunId: selected.runId || undefined,
+ options: { enabled: enabledDatasets },
+ });
+
+ const datasetEdges: WebserverEdge[] = [];
const rawNodes =
data?.nodes && datasetsCollection?.datasets?.length
? {
@@ -90,8 +118,6 @@ const Graph = ({ openGroupIds, onToggleGroups,
hoveredTaskState }: Props) => {
}
: data?.nodes;
- const datasetEdges: WebserverEdge[] = [];
-
datasetsCollection?.datasets?.forEach((dataset) => {
const producingTask = dataset?.producingTasks?.find(
(t) => t.dagId === dagId
@@ -126,8 +152,6 @@ const Graph = ({ openGroupIds, onToggleGroups,
hoveredTaskState }: Props) => {
arrange,
});
- const { selected } = useSelection();
-
const { colors } = useTheme();
const { getZoom, fitView } = useReactFlow();
const latestDagRunId = dagRuns[dagRuns.length - 1]?.runId;
@@ -151,6 +175,9 @@ const Graph = ({ openGroupIds, onToggleGroups,
hoveredTaskState }: Props) => {
groups,
hoveredTaskState,
isZoomedOut,
+ datasetEvents: selected.runId
+ ? [...upstreamDatasetEvents, ...downstreamDatasetEvents]
+ : [],
}),
[
graphData?.children,
@@ -161,6 +188,8 @@ const Graph = ({ openGroupIds, onToggleGroups,
hoveredTaskState }: Props) => {
groups,
hoveredTaskState,
isZoomedOut,
+ upstreamDatasetEvents,
+ downstreamDatasetEvents,
]
);
diff --git a/airflow/www/static/js/dag/details/graph/utils.ts
b/airflow/www/static/js/dag/details/graph/utils.ts
index bc9733aa62..93c8b9c253 100644
--- a/airflow/www/static/js/dag/details/graph/utils.ts
+++ b/airflow/www/static/js/dag/details/graph/utils.ts
@@ -24,6 +24,7 @@ import type { ElkExtendedEdge } from "elkjs";
import type { SelectionProps } from "src/dag/useSelection";
import { getTask } from "src/utils";
import type { Task, TaskInstance, NodeType } from "src/types";
+import type { DatasetEvent } from "src/types/api-generated";
import type { CustomNodeProps } from "./Node";
@@ -37,6 +38,7 @@ interface FlattenNodesProps {
onToggleGroups: (groupIds: string[]) => void;
hoveredTaskState?: string | null;
isZoomedOut: boolean;
+ datasetEvents?: DatasetEvent[];
}
// Generate a flattened list of nodes for react-flow to render
@@ -50,6 +52,7 @@ export const flattenNodes = ({
parent,
hoveredTaskState,
isZoomedOut,
+ datasetEvents,
}: FlattenNodesProps) => {
let nodes: ReactFlowNode<CustomNodeProps>[] = [];
let edges: ElkExtendedEdge[] = [];
@@ -88,6 +91,10 @@ export const flattenNodes = ({
}
onToggleGroups(newGroupIds);
},
+ datasetEvent:
+ node.value.class === "dataset"
+ ? datasetEvents?.find((de) => de.datasetUri === node.value.label)
+ : undefined,
...node.value,
},
type: "custom",