This is an automated email from the ASF dual-hosted git repository.
bbovenzi 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 91a93474377 Add asset event information to Dag Graph (#47410)
91a93474377 is described below
commit 91a934743773879f0ce8c863fa8b3340870cdf03
Author: Brent Bovenzi <[email protected]>
AuthorDate: Wed Mar 5 17:13:25 2025 -0500
Add asset event information to Dag Graph (#47410)
---
airflow/ui/src/components/Graph/AssetNode.tsx | 85 +++++++++++++++++++--------
airflow/ui/src/components/Graph/DagNode.tsx | 18 +++---
2 files changed, 70 insertions(+), 33 deletions(-)
diff --git a/airflow/ui/src/components/Graph/AssetNode.tsx
b/airflow/ui/src/components/Graph/AssetNode.tsx
index 8dab1d92605..828cd382bbb 100644
--- a/airflow/ui/src/components/Graph/AssetNode.tsx
+++ b/airflow/ui/src/components/Graph/AssetNode.tsx
@@ -16,35 +16,72 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { Flex, Heading, HStack } from "@chakra-ui/react";
+import { Flex, Heading, HStack, Text } from "@chakra-ui/react";
import type { NodeProps, Node as NodeType } from "@xyflow/react";
import { FiDatabase } from "react-icons/fi";
+import { useParams } from "react-router-dom";
+import { useAssetServiceGetAssetEvents, useDagRunServiceGetUpstreamAssetEvents
} from "openapi/queries";
+import { pluralize } from "src/utils";
+
+import Time from "../Time";
import { NodeWrapper } from "./NodeWrapper";
import type { CustomNodeProps } from "./reactflowUtils";
export const AssetNode = ({
data: { height, isSelected, label, width },
-}: NodeProps<NodeType<CustomNodeProps, "asset">>) => (
- <NodeWrapper>
- <Flex
- bg="bg"
- borderColor={isSelected ? "border.inverted" : "border"}
- borderRadius={5}
- borderWidth={isSelected ? 6 : 2}
- cursor="default"
- flexDirection="column"
- height={`${height}px`}
- px={3}
- py={isSelected ? 0 : 1}
- width={`${width}px`}
- >
- <HStack>
- <Heading ml={-2} size="sm">
- <FiDatabase />
- </Heading>
- {label}
- </HStack>
- </Flex>
- </NodeWrapper>
-);
+}: NodeProps<NodeType<CustomNodeProps, "asset">>) => {
+ const { dagId = "", runId = "" } = useParams();
+ const { data: upstreamEventsData } = useDagRunServiceGetUpstreamAssetEvents(
+ { dagId, dagRunId: runId },
+ undefined,
+ { enabled: Boolean(dagId) && Boolean(runId) },
+ );
+
+ const { data: downstreamEventsData } = useAssetServiceGetAssetEvents(
+ { sourceDagId: dagId, sourceRunId: runId },
+ undefined,
+ { enabled: Boolean(dagId) && Boolean(runId) },
+ );
+
+ const datasetEvent = [
+ ...(upstreamEventsData?.asset_events ?? []),
+ ...(downstreamEventsData?.asset_events ?? []),
+ ].find((event) => event.name === label);
+
+ return (
+ <NodeWrapper>
+ <Flex
+ bg="bg"
+ borderColor={isSelected ? "border.inverted" : "border"}
+ borderRadius={5}
+ borderWidth={isSelected ? 6 : 2}
+ cursor="default"
+ flexDirection="column"
+ height={`${height}px`}
+ px={3}
+ py={isSelected ? 0 : 1}
+ width={`${width}px`}
+ >
+ <HStack>
+ <Heading ml={-2} size="sm">
+ <FiDatabase />
+ </Heading>
+ {label}
+ </HStack>
+ {datasetEvent === undefined ? undefined : (
+ <>
+ <Text color="fg.muted">
+ <Time datetime={datasetEvent.timestamp} />
+ </Text>
+ {datasetEvent.created_dagruns.length &&
datasetEvent.created_dagruns.length > 1 ? (
+ <Text color="fg.muted" fontSize="sm">
+ +{pluralize("other Dag Run",
datasetEvent.created_dagruns.length)}
+ </Text>
+ ) : undefined}
+ </>
+ )}
+ </Flex>
+ </NodeWrapper>
+ );
+};
diff --git a/airflow/ui/src/components/Graph/DagNode.tsx
b/airflow/ui/src/components/Graph/DagNode.tsx
index a3925509c89..800411b9cec 100644
--- a/airflow/ui/src/components/Graph/DagNode.tsx
+++ b/airflow/ui/src/components/Graph/DagNode.tsx
@@ -45,17 +45,17 @@ export const DagNode = ({
py={isSelected ? 0 : 1}
width={`${width}px`}
>
- <HStack alignItems="center" gap={1}>
+ <HStack alignItems="center" justifyContent="space-between">
<DagIcon />
- <Link asChild color="fg.info" mb={2}>
- <RouterLink to={`/dags/${dag?.dag_id ??
label}`}>{dag?.dag_display_name ?? label}</RouterLink>
- </Link>
+ <TogglePause
+ dagId={dag?.dag_id ?? label}
+ disabled={!Boolean(dag)}
+ isPaused={dag?.is_paused ?? false}
+ />
</HStack>
- <TogglePause
- dagId={dag?.dag_id ?? label}
- disabled={!Boolean(dag)}
- isPaused={dag?.is_paused ?? false}
- />
+ <Link asChild color="fg.info" mb={2}>
+ <RouterLink to={`/dags/${dag?.dag_id ??
label}`}>{dag?.dag_display_name ?? label}</RouterLink>
+ </Link>
</Flex>
</NodeWrapper>
);