This is an automated email from the ASF dual-hosted git repository.
amoghrajesh 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 40aac72bef2 UI: Add a column in asset store display table linking to
the TI that wrote it (#68395)
40aac72bef2 is described below
commit 40aac72bef2d83523ec719f272e36362e03ce44d
Author: Amogh Desai <[email protected]>
AuthorDate: Fri Jun 12 09:38:41 2026 +0530
UI: Add a column in asset store display table linking to the TI that wrote
it (#68395)
---
.../airflow/ui/public/i18n/locales/en/assets.json | 3 ++
.../ui/src/pages/Asset/AssetStore/AssetStore.tsx | 57 ++++++++++++++++++++--
2 files changed, 57 insertions(+), 3 deletions(-)
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/en/assets.json
b/airflow-core/src/airflow/ui/public/i18n/locales/en/assets.json
index 2e933a2fbcc..95b7fe7c5da 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/en/assets.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/en/assets.json
@@ -13,6 +13,9 @@
"deleteWarning": "The asset will lose this persisted store entry.",
"edit": "Edit Asset Store",
"emptyState": "Asset store stores values scoped to an asset identity,
shared across all Dag runs. Workers can write asset store via the Task SDK.",
+ "lastUpdatedBy": "Last Updated By",
+ "lastUpdatedByApi": "API",
+ "lastUpdatedByWatcher": "Watcher",
"title": "Asset Store"
},
"consumingDags": "Consuming Dags",
diff --git
a/airflow-core/src/airflow/ui/src/pages/Asset/AssetStore/AssetStore.tsx
b/airflow-core/src/airflow/ui/src/pages/Asset/AssetStore/AssetStore.tsx
index 418a46b17cd..99ca52fc5be 100644
--- a/airflow-core/src/airflow/ui/src/pages/Asset/AssetStore/AssetStore.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Asset/AssetStore/AssetStore.tsx
@@ -16,24 +16,36 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { Flex, Text } from "@chakra-ui/react";
+import { Flex, Link, Text } from "@chakra-ui/react";
import type { ColumnDef } from "@tanstack/react-table";
import { useTranslation } from "react-i18next";
-import { useParams } from "react-router-dom";
+import { Link as RouterLink, useParams } from "react-router-dom";
import { useAssetStoreServiceListAssetStore } from "openapi/queries";
-import type { AssetStoreResponse } from "openapi/requests";
+import type { AssetStoreLastUpdatedBy, AssetStoreResponse } from
"openapi/requests";
import { DataTable } from "src/components/DataTable";
import { useTableURLState } from "src/components/DataTable/useTableUrlState";
import { ErrorAlert } from "src/components/ErrorAlert";
import { StoreValueCell } from "src/components/StoreValueCell";
import Time from "src/components/Time";
+import { getTaskInstanceLink } from "src/utils/links";
import { AddAssetStoreButton } from "./AddAssetStoreButton";
import { ClearAllAssetStoreButton } from "./ClearAllAssetStoreButton";
import { DeleteAssetStoreButton } from "./DeleteAssetStoreButton";
import { EditAssetStoreButton } from "./EditAssetStoreButton";
+type TaskWriter = { dag_id: string; run_id: string; task_id: string } &
AssetStoreLastUpdatedBy;
+
+const isTaskWriter = (writer: AssetStoreLastUpdatedBy): writer is TaskWriter =>
+ writer.kind === "task" &&
+ writer.dag_id !== null &&
+ writer.dag_id !== undefined &&
+ writer.run_id !== null &&
+ writer.run_id !== undefined &&
+ writer.task_id !== null &&
+ writer.task_id !== undefined;
+
type ColumnsProps = {
readonly assetId: number;
readonly translate: (key: string) => string;
@@ -56,6 +68,45 @@ const getColumns = ({ assetId, translate }: ColumnsProps):
Array<ColumnDef<Asset
cell: ({ row: { original } }) => <Time datetime={original.updated_at} />,
header: translate("common:table.updatedAt"),
},
+ {
+ accessorKey: "last_updated_by",
+ cell: ({ row: { original } }) => {
+ const writer = original.last_updated_by;
+
+ if (!writer) {
+ return <Text color="fg.muted">—</Text>;
+ }
+ if (isTaskWriter(writer)) {
+ const path = getTaskInstanceLink({
+ dagId: writer.dag_id,
+ dagRunId: writer.run_id,
+ mapIndex: writer.map_index ?? undefined,
+ taskId: writer.task_id,
+ });
+
+ return (
+ <Flex direction="column">
+ <Link asChild color="fg.info">
+ <RouterLink to={path}>{writer.task_id}</RouterLink>
+ </Link>
+ <Text color="fg.muted" fontSize="xs">
+ {writer.dag_id}
+ </Text>
+ </Flex>
+ );
+ }
+
+ return (
+ <Text>
+ {writer.kind === "api"
+ ? translate("assets:assetStore.lastUpdatedByApi")
+ : translate("assets:assetStore.lastUpdatedByWatcher")}
+ </Text>
+ );
+ },
+ enableSorting: false,
+ header: translate("assets:assetStore.lastUpdatedBy"),
+ },
{
accessorKey: "actions",
cell: ({ row: { original } }) => (