diff --git a/airflow-core/src/airflow/ui/src/i18n/locales/en/dag.json b/airflow-core/src/airflow/ui/src/i18n/locales/en/dag.json index f6e5dd3eaa685..2433357772b16 100644 --- a/airflow-core/src/airflow/ui/src/i18n/locales/en/dag.json +++ b/airflow-core/src/airflow/ui/src/i18n/locales/en/dag.json @@ -89,10 +89,11 @@ } }, "tabs": { + "asset_events": "Asset Events", "backfills": "Backfills", "code": "Code", "details": "Details", - "events": "Events", + "events": "Audit Logs", "overview": "Overview", "runs": "Runs", "tasks": "Tasks" diff --git a/airflow-core/src/airflow/ui/src/pages/Run/AssetEvents.tsx b/airflow-core/src/airflow/ui/src/pages/Run/AssetEvents.tsx new file mode 100644 index 0000000000000..c7fd536b95053 --- /dev/null +++ b/airflow-core/src/airflow/ui/src/pages/Run/AssetEvents.tsx @@ -0,0 +1,45 @@ +/*! + * 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 { useParams } from "react-router-dom"; + +import { useDagRunServiceGetDagRun, useDagRunServiceGetUpstreamAssetEvents } from "openapi/queries"; +import { AssetEvents as AssetEventsTable } from "src/components/Assets/AssetEvents"; +import { isStatePending, useAutoRefresh } from "src/utils"; + +export const AssetEvents = () => { + const { dagId = "", runId = "" } = useParams(); + + const refetchInterval = useAutoRefresh({ dagId }); + + const { data: dagRun } = useDagRunServiceGetDagRun( + { + dagId, + dagRunId: runId, + }, + undefined, + { refetchInterval: (query) => (isStatePending(query.state.data?.state) ? refetchInterval : false) }, + ); + + const { data, isLoading } = useDagRunServiceGetUpstreamAssetEvents({ dagId, dagRunId: runId }, undefined, { + enabled: dagRun?.run_type === "asset_triggered", + refetchInterval: () => (isStatePending(dagRun?.state) ? refetchInterval : false), + }); + + return ; +}; diff --git a/airflow-core/src/airflow/ui/src/pages/Run/Details.tsx b/airflow-core/src/airflow/ui/src/pages/Run/Details.tsx index 8a65fcafe6761..75860092487f0 100644 --- a/airflow-core/src/airflow/ui/src/pages/Run/Details.tsx +++ b/airflow-core/src/airflow/ui/src/pages/Run/Details.tsx @@ -19,8 +19,7 @@ import { Box, Flex, HStack, StackSeparator, Table, Text, VStack } from "@chakra-ui/react"; import { useParams } from "react-router-dom"; -import { useDagRunServiceGetDagRun, useDagRunServiceGetUpstreamAssetEvents } from "openapi/queries"; -import { AssetEvents } from "src/components/Assets/AssetEvents"; +import { useDagRunServiceGetDagRun } from "openapi/queries"; import { DagVersionDetails } from "src/components/DagVersionDetails"; import RenderedJsonField from "src/components/RenderedJsonField"; import { RunTypeIcon } from "src/components/RunTypeIcon"; @@ -43,17 +42,9 @@ export const Details = () => { { refetchInterval: (query) => (isStatePending(query.state.data?.state) ? refetchInterval : false) }, ); - const { data, isLoading } = useDagRunServiceGetUpstreamAssetEvents({ dagId, dagRunId: runId }, undefined, { - enabled: dagRun?.run_type === "asset_triggered", - refetchInterval: () => (isStatePending(dagRun?.state) ? refetchInterval : false), - }); - // TODO : Render DagRun configuration object return ( - {data === undefined || dagRun?.run_type !== "asset_triggered" ? undefined : ( - - )} {dagRun === undefined ? (
) : ( diff --git a/airflow-core/src/airflow/ui/src/pages/Run/Run.tsx b/airflow-core/src/airflow/ui/src/pages/Run/Run.tsx index 04ffb61cd89a9..5b4dfffd3e5ac 100644 --- a/airflow-core/src/airflow/ui/src/pages/Run/Run.tsx +++ b/airflow-core/src/airflow/ui/src/pages/Run/Run.tsx @@ -17,7 +17,7 @@ * under the License. */ import { ReactFlowProvider } from "@xyflow/react"; -import { FiCode } from "react-icons/fi"; +import { FiCode, FiDatabase } from "react-icons/fi"; import { MdDetails, MdOutlineEventNote, MdOutlineTask } from "react-icons/md"; import { useParams } from "react-router-dom"; @@ -29,9 +29,10 @@ import { Header } from "./Header"; const tabs = [ { icon: , label: "Task Instances", value: "" }, - { icon: , label: "Events", value: "events" }, + { icon: , label: "Audit Logs", value: "events" }, { icon: , label: "Code", value: "code" }, { icon: , label: "Details", value: "details" }, + { icon: , label: "Asset Events", value: "asset_events" }, ]; export const Run = () => { diff --git a/airflow-core/src/airflow/ui/src/pages/Task/Task.tsx b/airflow-core/src/airflow/ui/src/pages/Task/Task.tsx index dd20f01a03f93..0dc3dce538cf1 100644 --- a/airflow-core/src/airflow/ui/src/pages/Task/Task.tsx +++ b/airflow-core/src/airflow/ui/src/pages/Task/Task.tsx @@ -31,7 +31,7 @@ import { Header } from "./Header"; const tabs = [ { icon: , label: "Overview", value: "" }, { icon: , label: "Task Instances", value: "task_instances" }, - { icon: , label: "Events", value: "events" }, + { icon: , label: "Audit Logs", value: "events" }, ]; export const Task = () => { diff --git a/airflow-core/src/airflow/ui/src/pages/TaskInstance/AssetEvents.tsx b/airflow-core/src/airflow/ui/src/pages/TaskInstance/AssetEvents.tsx new file mode 100644 index 0000000000000..d5917aa8aab28 --- /dev/null +++ b/airflow-core/src/airflow/ui/src/pages/TaskInstance/AssetEvents.tsx @@ -0,0 +1,51 @@ +/*! + * 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 { useParams } from "react-router-dom"; + +import { useAssetServiceGetAssetEvents, useTaskInstanceServiceGetMappedTaskInstance } from "openapi/queries"; +import { AssetEvents as AssetEventsTable } from "src/components/Assets/AssetEvents"; +import { isStatePending, useAutoRefresh } from "src/utils"; + +export const AssetEvents = () => { + const { dagId = "", mapIndex = "-1", runId = "", taskId = "" } = useParams(); + + const { data: taskInstance } = useTaskInstanceServiceGetMappedTaskInstance({ + dagId, + dagRunId: runId, + mapIndex: parseInt(mapIndex, 10), + taskId, + }); + + const refetchInterval = useAutoRefresh({ dagId }); + + const { data: assetEventsData, isLoading } = useAssetServiceGetAssetEvents( + { + sourceDagId: dagId, + sourceMapIndex: parseInt(mapIndex, 10), + sourceRunId: runId, + sourceTaskId: taskId, + }, + undefined, + { + refetchInterval: () => (isStatePending(taskInstance?.state) ? refetchInterval : false), + }, + ); + + return ; +}; diff --git a/airflow-core/src/airflow/ui/src/pages/TaskInstance/Details.tsx b/airflow-core/src/airflow/ui/src/pages/TaskInstance/Details.tsx index f02b27dbcfc4c..9fed186008ffc 100644 --- a/airflow-core/src/airflow/ui/src/pages/TaskInstance/Details.tsx +++ b/airflow-core/src/airflow/ui/src/pages/TaskInstance/Details.tsx @@ -20,11 +20,9 @@ import { Box, Flex, HStack, Table, Heading } from "@chakra-ui/react"; import { useParams, useSearchParams } from "react-router-dom"; import { - useAssetServiceGetAssetEvents, useTaskInstanceServiceGetMappedTaskInstance, useTaskInstanceServiceGetTaskInstanceTryDetails, } from "openapi/queries"; -import { AssetEvents } from "src/components/Assets/AssetEvents"; import { DagVersionDetails } from "src/components/DagVersionDetails"; import { StateBadge } from "src/components/StateBadge"; import { TaskTrySelect } from "src/components/TaskTrySelect"; @@ -76,24 +74,8 @@ export const Details = () => { }, ); - const { data: assetEventsData, isLoading: isLoadingAssetEvents } = useAssetServiceGetAssetEvents( - { - sourceDagId: dagId, - sourceMapIndex: parseInt(mapIndex, 10), - sourceRunId: runId, - sourceTaskId: taskId, - }, - undefined, - { - refetchInterval: () => (isStatePending(taskInstance?.state) ? refetchInterval : false), - }, - ); - return ( - {assetEventsData !== undefined && assetEventsData.asset_events.length > 0 ? ( - - ) : undefined} {taskInstance === undefined || tryNumber === undefined || taskInstance.try_number <= 1 ? (
) : ( diff --git a/airflow-core/src/airflow/ui/src/pages/TaskInstance/TaskInstance.tsx b/airflow-core/src/airflow/ui/src/pages/TaskInstance/TaskInstance.tsx index 8e19e7dbec21b..c11fce7674107 100644 --- a/airflow-core/src/airflow/ui/src/pages/TaskInstance/TaskInstance.tsx +++ b/airflow-core/src/airflow/ui/src/pages/TaskInstance/TaskInstance.tsx @@ -17,7 +17,7 @@ * under the License. */ import { ReactFlowProvider } from "@xyflow/react"; -import { FiCode } from "react-icons/fi"; +import { FiCode, FiDatabase } from "react-icons/fi"; import { MdDetails, MdOutlineEventNote, MdOutlineTask, MdReorder, MdSyncAlt } from "react-icons/md"; import { PiBracketsCurlyBold } from "react-icons/pi"; import { useParams } from "react-router-dom"; @@ -36,9 +36,10 @@ const tabs = [ { icon: , label: "Logs", value: "" }, { icon: , label: "Rendered Templates", value: "rendered_templates" }, { icon: , label: "XCom", value: "xcom" }, - { icon: , label: "Events", value: "events" }, + { icon: , label: "Audit Logs", value: "events" }, { icon: , label: "Code", value: "code" }, { icon: , label: "Details", value: "details" }, + { icon: , label: "Asset Events", value: "asset_events" }, ]; export const TaskInstance = () => { diff --git a/airflow-core/src/airflow/ui/src/router.tsx b/airflow-core/src/airflow/ui/src/router.tsx index 3b7edfdb39e54..a5ff686277169 100644 --- a/airflow-core/src/airflow/ui/src/router.tsx +++ b/airflow-core/src/airflow/ui/src/router.tsx @@ -54,7 +54,9 @@ import { XCom } from "src/pages/XCom"; import { Configs } from "./pages/Configs"; import { GroupTaskInstance } from "./pages/GroupTaskInstance"; +import { AssetEvents as DagRunAssetEvents } from "./pages/Run/AssetEvents"; import { Security } from "./pages/Security"; +import { AssetEvents as TaskInstanceAssetEvents } from "./pages/TaskInstance/AssetEvents"; import { client } from "./queryClient"; const taskInstanceRoutes = [ @@ -65,6 +67,7 @@ const taskInstanceRoutes = [ { element: , path: "details" }, { element: , path: "rendered_templates" }, { element: , path: "task_instances" }, + { element: , path: "asset_events" }, ]; export const routerConfig = [ @@ -157,6 +160,7 @@ export const routerConfig = [ { element: , path: "events" }, { element: , path: "code" }, { element: , path: "details" }, + { element: , path: "asset_events" }, ], element: , path: "dags/:dagId/runs/:runId",