From 5162cd57fc406ca5ce0351745647d482f5014e72 Mon Sep 17 00:00:00 2001 From: seanyu Date: Sun, 9 Nov 2025 15:35:02 +0800 Subject: [PATCH 1/9] Add several filters to Task View (squashed, de-duplicated) --- .../ui/public/i18n/locales/en/common.json | 1 + .../ui/src/constants/filterConfigs.tsx | 49 +++- .../airflow/ui/src/constants/searchParams.ts | 4 + .../src/pages/TaskInstances/TaskInstances.tsx | 52 +++-- .../TaskInstances/TaskInstancesFilter.tsx | 218 +++++++----------- .../airflow/ui/src/utils/useFiltersHandler.ts | 4 + 6 files changed, 181 insertions(+), 147 deletions(-) diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/en/common.json b/airflow-core/src/airflow/ui/public/i18n/locales/en/common.json index 349b598e92133..c8d4ab1523cbe 100644 --- a/airflow-core/src/airflow/ui/public/i18n/locales/en/common.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/en/common.json @@ -240,6 +240,7 @@ "executorConfig": "Executor Config", "hostname": "Hostname", "maxTries": "Max Tries", + "operator": "Operator", "pid": "PID", "pool": "Pool", "poolSlots": "Pool Slots", diff --git a/airflow-core/src/airflow/ui/src/constants/filterConfigs.tsx b/airflow-core/src/airflow/ui/src/constants/filterConfigs.tsx index a845244800abf..03b2c91d413df 100644 --- a/airflow-core/src/airflow/ui/src/constants/filterConfigs.tsx +++ b/airflow-core/src/airflow/ui/src/constants/filterConfigs.tsx @@ -20,6 +20,8 @@ import { Flex } from "@chakra-ui/react"; import { useTranslation } from "react-i18next"; import { FiBarChart, FiUser } from "react-icons/fi"; import { LuBrackets } from "react-icons/lu"; +import { PiQueue } from "react-icons/pi"; +import { BiTargetLock } from "react-icons/bi"; import { MdDateRange, MdSearch, @@ -28,15 +30,16 @@ import { MdCode, MdPlayArrow, MdCheckCircle, + MdBuild, } from "react-icons/md"; -import type { DagRunState, DagRunType } from "openapi/requests/types.gen"; +import type { DagRunState, DagRunType, TaskInstanceState } from "openapi/requests/types.gen"; import { DagIcon } from "src/assets/DagIcon"; import { TaskIcon } from "src/assets/TaskIcon"; import type { FilterConfig } from "src/components/FilterBar"; import { RunTypeIcon } from "src/components/RunTypeIcon"; import { StateBadge } from "src/components/StateBadge"; -import { dagRunStateOptions, dagRunTypeOptions } from "src/constants/stateOptions"; +import { dagRunStateOptions, dagRunTypeOptions, taskInstanceStateOptions } from "src/constants/stateOptions"; import { SearchParamsKeys } from "./searchParams"; @@ -144,6 +147,30 @@ export const useFilterConfigs = () => { min: -1, type: FilterTypes.NUMBER, }, + [SearchParamsKeys.NAME_PATTERN]: { + hotkeyDisabled: true, + icon: , + label: translate("common:taskId"), + type: FilterTypes.TEXT, + }, + [SearchParamsKeys.OPERATOR_NAME_PATTERN]: { + hotkeyDisabled: true, + icon: , + label: translate("common:taskInstance.operator"), + type: FilterTypes.TEXT, + }, + [SearchParamsKeys.POOL_NAME_PATTERN]: { + hotkeyDisabled: true, + icon: , + label: translate("common:taskInstance.pool"), + type: FilterTypes.TEXT, + }, + [SearchParamsKeys.QUEUE_NAME_PATTERN]: { + hotkeyDisabled: true, + icon: , + label: translate("common:taskInstance.queue"), + type: FilterTypes.TEXT, + }, [SearchParamsKeys.RESPONDED_BY_USER_NAME]: { hotkeyDisabled: true, icon: , @@ -233,6 +260,24 @@ export const useFilterConfigs = () => { label: translate("common:taskId"), type: FilterTypes.TEXT, }, + [SearchParamsKeys.TASK_STATE]: { + icon: , + label: translate("common:state"), + options: taskInstanceStateOptions.items.map((option) => ({ + label: + option.value === "all" ? ( + translate(option.label) + ) : ( + {translate(option.label)} + ), + value: option.value === "all" ? ( + "" + ):( + option.value + ), + })), + type: FilterTypes.SELECT, + }, [SearchParamsKeys.TRIGGERING_USER_NAME_PATTERN]: { hotkeyDisabled: true, icon: , diff --git a/airflow-core/src/airflow/ui/src/constants/searchParams.ts b/airflow-core/src/airflow/ui/src/constants/searchParams.ts index 17be1231adaf9..88f2733942386 100644 --- a/airflow-core/src/airflow/ui/src/constants/searchParams.ts +++ b/airflow-core/src/airflow/ui/src/constants/searchParams.ts @@ -54,6 +54,9 @@ export enum SearchParamsKeys { OWNERS = "owners", PAUSED = "paused", POOL = "pool", + POOL_NAME_PATTERN = "pool_name_pattern", + QUEUE_NAME_PATTERN = "queue_name_pattern", + OPERATOR_NAME_PATTERN = "operator_name_pattern", RESPONDED_BY_USER_NAME = "responded_by_user_name", RESPONSE_RECEIVED = "response_received", RETRIES = "retries", @@ -72,6 +75,7 @@ export enum SearchParamsKeys { TAGS_MATCH_MODE = "tags_match_mode", TASK_ID = "task_id", TASK_ID_PATTERN = "task_id_pattern", + TASK_STATE = "task_state", TRIGGER_RULE = "trigger_rule", TRIGGERING_USER_NAME_PATTERN = "triggering_user_name_pattern", TRY_NUMBER = "try_number", diff --git a/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsx b/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsx index 9d13622ffe1dc..13768ba5bacaf 100644 --- a/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsx +++ b/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsx @@ -21,7 +21,7 @@ import { Flex, Link } from "@chakra-ui/react"; import type { ColumnDef } from "@tanstack/react-table"; import type { TFunction } from "i18next"; -import { useMemo, useState } from "react"; +import { useMemo } from "react"; import { useTranslation } from "react-i18next"; import { Link as RouterLink, useParams, useSearchParams } from "react-router-dom"; @@ -47,11 +47,21 @@ type TaskInstanceRow = { row: { original: TaskInstanceResponse } }; const { DAG_ID_PATTERN: DAG_ID_PATTERN_PARAM, + DAG_VERSION: DAG_VERSION_PARAM, + DURATION_GTE: DURATION_GTE_PARAM, + DURATION_LTE: DURATION_LTE_PARAM, END_DATE: END_DATE_PARAM, + LOGICAL_DATE_GTE: LOGICAL_DATE_GTE_PARAM, + LOGICAL_DATE_LTE: LOGICAL_DATE_LTE_PARAM, + MAP_INDEX: MAP_INDEX_PARAM, NAME_PATTERN: NAME_PATTERN_PARAM, - POOL: POOL_PARAM, + OPERATOR_NAME_PATTERN: OPERATOR_NAME_PATTERN_PARAM, + POOL_NAME_PATTERN: POOL_NAME_PATTERN_PARAM, + QUEUE_NAME_PATTERN: QUEUE_NAME_PATTERN_PARAM, + RUN_ID: RUN_ID_PARAM, START_DATE: START_DATE_PARAM, - STATE: STATE_PARAM, + TASK_STATE: STATE_PARAM, + TRY_NUMBER: TRY_NUMBER_PARAM, }: SearchParamsKeysType = SearchParamsKeys; const taskInstanceColumns = ({ @@ -229,16 +239,23 @@ export const TaskInstances = () => { const orderBy = sort ? [`${sort.desc ? "-" : ""}${sort.id}`] : ["-start_date", "-run_after"]; const filteredState = searchParams.getAll(STATE_PARAM); + const filteredDagVersion = searchParams.get(DAG_VERSION_PARAM); + const durationGte = searchParams.get(DURATION_GTE_PARAM); + const durationLte = searchParams.get(DURATION_LTE_PARAM); + const logicalDateGte = searchParams.get(LOGICAL_DATE_GTE_PARAM); + const logicalDateLte = searchParams.get(LOGICAL_DATE_LTE_PARAM); + const tryNumberFilter = searchParams.get(TRY_NUMBER_PARAM); + const mapIndexFilter = searchParams.get(MAP_INDEX_PARAM); const startDate = searchParams.get(START_DATE_PARAM); const endDate = searchParams.get(END_DATE_PARAM); - const pool = searchParams.getAll(POOL_PARAM); + const poolNamePattern = searchParams.get(POOL_NAME_PATTERN_PARAM); + const queueNamePattern = searchParams.get(QUEUE_NAME_PATTERN_PARAM); + const operatorNamePattern = searchParams.get(OPERATOR_NAME_PATTERN_PARAM); const filteredDagIdPattern = searchParams.get(DAG_ID_PATTERN_PARAM); + const filteredRunId = searchParams.get(RUN_ID_PARAM); const hasFilteredState = filteredState.length > 0; - const hasFilteredPool = pool.length > 0; + const taskDisplayNamePattern= searchParams.get(NAME_PATTERN_PARAM); - const [taskDisplayNamePattern, setTaskDisplayNamePattern] = useState( - searchParams.get(NAME_PATTERN_PARAM) ?? undefined, - ); const refetchInterval = useAutoRefresh({}); @@ -246,16 +263,26 @@ export const TaskInstances = () => { { dagId: dagId ?? "~", dagIdPattern: filteredDagIdPattern ?? undefined, - dagRunId: runId ?? "~", + dagRunId: runId ?? filteredRunId ?? "~", + durationGte: durationGte !== null && durationGte !== "" ? Number(durationGte) : undefined, + durationLte: durationLte !== null && durationLte !== "" ? Number(durationLte) : undefined, endDateLte: endDate ?? undefined, limit: pagination.pageSize, + logicalDateGte: logicalDateGte ?? undefined, + logicalDateLte: logicalDateLte ?? undefined, + mapIndex: mapIndexFilter !== null && mapIndexFilter !== "" ? [Number(mapIndexFilter)] : undefined, offset: pagination.pageIndex * pagination.pageSize, orderBy, - pool: hasFilteredPool ? pool : undefined, + poolNamePattern: poolNamePattern ?? undefined, + queueNamePattern: queueNamePattern ?? undefined, + operatorNamePattern: operatorNamePattern ?? undefined, startDateGte: startDate ?? undefined, state: hasFilteredState ? filteredState : undefined, taskDisplayNamePattern: groupId ?? taskDisplayNamePattern ?? undefined, taskId: Boolean(groupId) ? undefined : taskId, + tryNumber: tryNumberFilter !== null && tryNumberFilter !== "" ? [Number(tryNumberFilter)] : undefined, + versionNumber: + filteredDagVersion !== null && filteredDagVersion !== "" ? [Number(filteredDagVersion)] : undefined, }, undefined, { @@ -277,10 +304,7 @@ export const TaskInstances = () => { return ( <> - + >; - readonly taskDisplayNamePattern: string | undefined; -}) => { - const { dagId, runId } = useParams(); - const [searchParams, setSearchParams] = useSearchParams(); - const { setTableURLState, tableURLState } = useTableURLState(); - const { pagination, sorting } = tableURLState; - const { t: translate } = useTranslation(); - - const filteredState = searchParams.getAll(STATE_PARAM); - const filteredDagIdPattern = searchParams.get(DAG_ID_PATTERN_PARAM); - const hasFilteredState = filteredState.length > 0; - - const handleStateChange = useCallback( - ({ value }: SelectValueChangeDetails) => { - const [val, ...rest] = value; - - if ((val === undefined || val === "all") && rest.length === 0) { - searchParams.delete(STATE_PARAM); - } else { - searchParams.delete(STATE_PARAM); - value.filter((state) => state !== "all").map((state) => searchParams.append(STATE_PARAM, state)); - } - setTableURLState({ - pagination: { ...pagination, pageIndex: 0 }, - sorting, - }); - setSearchParams(searchParams); - }, - [pagination, searchParams, setSearchParams, setTableURLState, sorting], - ); - const handleSearchChange = (value: string) => { - if (value) { - searchParams.set(NAME_PATTERN_PARAM, value); - } else { - searchParams.delete(NAME_PATTERN_PARAM); + +export const TaskInstancesFilter = () => { + const {dagId, runId } = useParams(); + const paramKeys = useMemo((): Array => { + const keys: Array = [ + NAME_PATTERN_PARAM as FilterableSearchParamsKeys, + LOGICAL_DATE_GTE_PARAM as FilterableSearchParamsKeys, + LOGICAL_DATE_LTE_PARAM as FilterableSearchParamsKeys, + START_DATE_PARAM as FilterableSearchParamsKeys, + END_DATE_PARAM as FilterableSearchParamsKeys, + DURATION_GTE_PARAM as FilterableSearchParamsKeys, + DURATION_LTE_PARAM as FilterableSearchParamsKeys, + TRY_NUMBER_PARAM as FilterableSearchParamsKeys, + MAP_INDEX_PARAM as FilterableSearchParamsKeys, + DAG_VERSION_PARAM as FilterableSearchParamsKeys, + OPERATOR_NAME_PATTERN_PARAM as FilterableSearchParamsKeys, + POOL_NAME_PATTERN_PARAM as FilterableSearchParamsKeys, + QUEUE_NAME_PATTERN_PARAM as FilterableSearchParamsKeys, + STATE_PARAM as FilterableSearchParamsKeys, + ]; + + if (runId === undefined) { + keys.unshift(RUN_ID_PARAM as FilterableSearchParamsKeys); } - setTableURLState({ - pagination: { ...pagination, pageIndex: 0 }, - sorting, - }); - setTaskDisplayNamePattern(value); - setSearchParams(searchParams); - }; - - const handleDagIdPatternChange = useCallback( - (value: string) => { - if (value === "") { - searchParams.delete(DAG_ID_PATTERN_PARAM); - } else { - searchParams.set(DAG_ID_PATTERN_PARAM, value); + + if (dagId === undefined) { + keys.unshift(DAG_ID_PATTERN_PARAM as FilterableSearchParamsKeys); + } + + return keys; + }, [dagId, runId]); + + const [searchParams] = useSearchParams(); + + + + + const { filterConfigs, handleFiltersChange } = useFiltersHandler(paramKeys); + + + + const initialValues = useMemo(() => { + const values: Record = {}; + + filterConfigs.forEach((config) => { + const value = searchParams.get(config.key); + + if (value !== null && value !== "") { + if (config.type === "number") { + const parsedValue = Number(value); + + values[config.key] = isNaN(parsedValue) ? value : parsedValue; + } else { + values[config.key] = value; + } } - setTableURLState({ - pagination: { ...pagination, pageIndex: 0 }, - sorting, - }); - setSearchParams(searchParams); - }, - [pagination, searchParams, setSearchParams, setTableURLState, sorting], - ); + }); + + return values; + }, [searchParams, filterConfigs]); + return ( - - {dagId === undefined && ( - + + + - )} - - - - - {() => - hasFilteredState ? ( - - {filteredState.map((state) => ( - - {translate(`common:states.${state}`)} - - ))} - - ) : ( - translate("dags:filters.allStates") - ) - } - - - - {taskInstanceStateOptions.items.map((option) => ( - - {option.value === "all" ? ( - translate(option.label) - ) : ( - {translate(option.label)} - )} - - ))} - - - + + ); }; diff --git a/airflow-core/src/airflow/ui/src/utils/useFiltersHandler.ts b/airflow-core/src/airflow/ui/src/utils/useFiltersHandler.ts index e4f900600549f..6308b431474b6 100644 --- a/airflow-core/src/airflow/ui/src/utils/useFiltersHandler.ts +++ b/airflow-core/src/airflow/ui/src/utils/useFiltersHandler.ts @@ -72,6 +72,10 @@ export type FilterableSearchParamsKeys = | SearchParamsKeys.KEY_PATTERN | SearchParamsKeys.LOGICAL_DATE_RANGE | SearchParamsKeys.MAP_INDEX + | SearchParamsKeys.NAME_PATTERN + | SearchParamsKeys.POOL_NAME_PATTERN + | SearchParamsKeys.QUEUE_NAME_PATTERN + | SearchParamsKeys.OPERATOR_NAME_PATTERN | SearchParamsKeys.RESPONDED_BY_USER_NAME | SearchParamsKeys.RESPONSE_RECEIVED | SearchParamsKeys.RUN_AFTER_RANGE From 3eb0fb0b919b34856ec2242cb0751edc95094d48 Mon Sep 17 00:00:00 2001 From: seanyu Date: Wed, 12 Nov 2025 15:52:50 +0800 Subject: [PATCH 2/9] fix traslation problem stick to Operator in task --- airflow-core/src/airflow/ui/public/i18n/locales/en/common.json | 1 - airflow-core/src/airflow/ui/src/constants/filterConfigs.tsx | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/en/common.json b/airflow-core/src/airflow/ui/public/i18n/locales/en/common.json index c8d4ab1523cbe..349b598e92133 100644 --- a/airflow-core/src/airflow/ui/public/i18n/locales/en/common.json +++ b/airflow-core/src/airflow/ui/public/i18n/locales/en/common.json @@ -240,7 +240,6 @@ "executorConfig": "Executor Config", "hostname": "Hostname", "maxTries": "Max Tries", - "operator": "Operator", "pid": "PID", "pool": "Pool", "poolSlots": "Pool Slots", diff --git a/airflow-core/src/airflow/ui/src/constants/filterConfigs.tsx b/airflow-core/src/airflow/ui/src/constants/filterConfigs.tsx index 03b2c91d413df..313fa54435253 100644 --- a/airflow-core/src/airflow/ui/src/constants/filterConfigs.tsx +++ b/airflow-core/src/airflow/ui/src/constants/filterConfigs.tsx @@ -156,7 +156,7 @@ export const useFilterConfigs = () => { [SearchParamsKeys.OPERATOR_NAME_PATTERN]: { hotkeyDisabled: true, icon: , - label: translate("common:taskInstance.operator"), + label: translate("common:task.operator"), type: FilterTypes.TEXT, }, [SearchParamsKeys.POOL_NAME_PATTERN]: { From de5cfae4537633f4db367645517dc72bd259b658 Mon Sep 17 00:00:00 2001 From: seanyu Date: Wed, 12 Nov 2025 16:06:56 +0800 Subject: [PATCH 3/9] fix format --- airflow-core/src/airflow/ui/src/constants/searchParams.ts | 2 +- .../src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsx | 2 +- airflow-core/src/airflow/ui/src/utils/useFiltersHandler.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/airflow-core/src/airflow/ui/src/constants/searchParams.ts b/airflow-core/src/airflow/ui/src/constants/searchParams.ts index 88f2733942386..91e2a0be00f03 100644 --- a/airflow-core/src/airflow/ui/src/constants/searchParams.ts +++ b/airflow-core/src/airflow/ui/src/constants/searchParams.ts @@ -51,12 +51,12 @@ export enum SearchParamsKeys { NEEDS_REVIEW = "needs_review", OFFSET = "offset", OPERATOR = "operator", + OPERATOR_NAME_PATTERN = "operator_name_pattern", OWNERS = "owners", PAUSED = "paused", POOL = "pool", POOL_NAME_PATTERN = "pool_name_pattern", QUEUE_NAME_PATTERN = "queue_name_pattern", - OPERATOR_NAME_PATTERN = "operator_name_pattern", RESPONDED_BY_USER_NAME = "responded_by_user_name", RESPONSE_RECEIVED = "response_received", RETRIES = "retries", diff --git a/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsx b/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsx index 13768ba5bacaf..f43abc1db8ccf 100644 --- a/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsx +++ b/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsx @@ -272,10 +272,10 @@ export const TaskInstances = () => { logicalDateLte: logicalDateLte ?? undefined, mapIndex: mapIndexFilter !== null && mapIndexFilter !== "" ? [Number(mapIndexFilter)] : undefined, offset: pagination.pageIndex * pagination.pageSize, + operatorNamePattern: operatorNamePattern ?? undefined, orderBy, poolNamePattern: poolNamePattern ?? undefined, queueNamePattern: queueNamePattern ?? undefined, - operatorNamePattern: operatorNamePattern ?? undefined, startDateGte: startDate ?? undefined, state: hasFilteredState ? filteredState : undefined, taskDisplayNamePattern: groupId ?? taskDisplayNamePattern ?? undefined, diff --git a/airflow-core/src/airflow/ui/src/utils/useFiltersHandler.ts b/airflow-core/src/airflow/ui/src/utils/useFiltersHandler.ts index 6308b431474b6..298a1c357da12 100644 --- a/airflow-core/src/airflow/ui/src/utils/useFiltersHandler.ts +++ b/airflow-core/src/airflow/ui/src/utils/useFiltersHandler.ts @@ -73,9 +73,9 @@ export type FilterableSearchParamsKeys = | SearchParamsKeys.LOGICAL_DATE_RANGE | SearchParamsKeys.MAP_INDEX | SearchParamsKeys.NAME_PATTERN + | SearchParamsKeys.OPERATOR_NAME_PATTERN | SearchParamsKeys.POOL_NAME_PATTERN | SearchParamsKeys.QUEUE_NAME_PATTERN - | SearchParamsKeys.OPERATOR_NAME_PATTERN | SearchParamsKeys.RESPONDED_BY_USER_NAME | SearchParamsKeys.RESPONSE_RECEIVED | SearchParamsKeys.RUN_AFTER_RANGE From 2556df09a19f20eea035052d84e7f56255ba5216 Mon Sep 17 00:00:00 2001 From: seanyu Date: Wed, 12 Nov 2025 16:44:19 +0800 Subject: [PATCH 4/9] fix too long file --- airflow-core/src/airflow/ui/src/constants/filterConfigs.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/airflow-core/src/airflow/ui/src/constants/filterConfigs.tsx b/airflow-core/src/airflow/ui/src/constants/filterConfigs.tsx index 313fa54435253..f4eb0173a8fdd 100644 --- a/airflow-core/src/airflow/ui/src/constants/filterConfigs.tsx +++ b/airflow-core/src/airflow/ui/src/constants/filterConfigs.tsx @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +/* eslint-disable max-lines */ import { Flex } from "@chakra-ui/react"; import { useTranslation } from "react-i18next"; import { FiBarChart, FiUser } from "react-icons/fi"; From 0d35dbe194c81416e9e6c7a96cd6151321fa4c7b Mon Sep 17 00:00:00 2001 From: seanyu Date: Wed, 12 Nov 2025 16:59:43 +0800 Subject: [PATCH 5/9] fix format --- .../airflow/ui/src/constants/filterConfigs.tsx | 13 +++++-------- .../ui/src/pages/TaskInstances/TaskInstances.tsx | 9 ++++----- .../pages/TaskInstances/TaskInstancesFilter.tsx | 16 +++------------- 3 files changed, 12 insertions(+), 26 deletions(-) diff --git a/airflow-core/src/airflow/ui/src/constants/filterConfigs.tsx b/airflow-core/src/airflow/ui/src/constants/filterConfigs.tsx index f4eb0173a8fdd..9baa23512747e 100644 --- a/airflow-core/src/airflow/ui/src/constants/filterConfigs.tsx +++ b/airflow-core/src/airflow/ui/src/constants/filterConfigs.tsx @@ -16,13 +16,13 @@ * specific language governing permissions and limitations * under the License. */ + /* eslint-disable max-lines */ import { Flex } from "@chakra-ui/react"; import { useTranslation } from "react-i18next"; +import { BiTargetLock } from "react-icons/bi"; import { FiBarChart, FiUser } from "react-icons/fi"; import { LuBrackets } from "react-icons/lu"; -import { PiQueue } from "react-icons/pi"; -import { BiTargetLock } from "react-icons/bi"; import { MdDateRange, MdSearch, @@ -33,6 +33,7 @@ import { MdCheckCircle, MdBuild, } from "react-icons/md"; +import { PiQueue } from "react-icons/pi"; import type { DagRunState, DagRunType, TaskInstanceState } from "openapi/requests/types.gen"; import { DagIcon } from "src/assets/DagIcon"; @@ -269,13 +270,9 @@ export const useFilterConfigs = () => { option.value === "all" ? ( translate(option.label) ) : ( - {translate(option.label)} + {translate(option.label)} ), - value: option.value === "all" ? ( - "" - ):( - option.value - ), + value: option.value === "all" ? "" : option.value, })), type: FilterTypes.SELECT, }, diff --git a/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsx b/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsx index f43abc1db8ccf..2a28b1b91abde 100644 --- a/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsx +++ b/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsx @@ -254,8 +254,7 @@ export const TaskInstances = () => { const filteredDagIdPattern = searchParams.get(DAG_ID_PATTERN_PARAM); const filteredRunId = searchParams.get(RUN_ID_PARAM); const hasFilteredState = filteredState.length > 0; - const taskDisplayNamePattern= searchParams.get(NAME_PATTERN_PARAM); - + const taskDisplayNamePattern = searchParams.get(NAME_PATTERN_PARAM); const refetchInterval = useAutoRefresh({}); @@ -274,8 +273,8 @@ export const TaskInstances = () => { offset: pagination.pageIndex * pagination.pageSize, operatorNamePattern: operatorNamePattern ?? undefined, orderBy, - poolNamePattern: poolNamePattern ?? undefined, - queueNamePattern: queueNamePattern ?? undefined, + poolNamePattern: poolNamePattern ?? undefined, + queueNamePattern: queueNamePattern ?? undefined, startDateGte: startDate ?? undefined, state: hasFilteredState ? filteredState : undefined, taskDisplayNamePattern: groupId ?? taskDisplayNamePattern ?? undefined, @@ -304,7 +303,7 @@ export const TaskInstances = () => { return ( <> - + { - const {dagId, runId } = useParams(); + const { dagId, runId } = useParams(); const paramKeys = useMemo((): Array => { const keys: Array = [ NAME_PATTERN_PARAM as FilterableSearchParamsKeys, @@ -67,11 +64,11 @@ export const TaskInstancesFilter = () => { ]; if (runId === undefined) { - keys.unshift(RUN_ID_PARAM as FilterableSearchParamsKeys); + keys.unshift(RUN_ID_PARAM as FilterableSearchParamsKeys); } if (dagId === undefined) { - keys.unshift(DAG_ID_PATTERN_PARAM as FilterableSearchParamsKeys); + keys.unshift(DAG_ID_PATTERN_PARAM as FilterableSearchParamsKeys); } return keys; @@ -79,13 +76,8 @@ export const TaskInstancesFilter = () => { const [searchParams] = useSearchParams(); - - - const { filterConfigs, handleFiltersChange } = useFiltersHandler(paramKeys); - - const initialValues = useMemo(() => { const values: Record = {}; @@ -106,10 +98,8 @@ export const TaskInstancesFilter = () => { return values; }, [searchParams, filterConfigs]); - return ( - Date: Sun, 16 Nov 2025 02:33:17 +0800 Subject: [PATCH 6/9] add run_id_pattern as backend filter --- .../core_api/openapi/v2-rest-api-generated.yaml | 12 ++++++++++++ .../core_api/routes/public/task_instances.py | 2 ++ .../src/airflow/ui/openapi-gen/queries/common.ts | 5 +++-- .../ui/openapi-gen/queries/ensureQueryData.ts | 6 ++++-- .../src/airflow/ui/openapi-gen/queries/prefetch.ts | 6 ++++-- .../src/airflow/ui/openapi-gen/queries/queries.ts | 6 ++++-- .../src/airflow/ui/openapi-gen/queries/suspense.ts | 6 ++++-- .../airflow/ui/openapi-gen/requests/services.gen.ts | 2 ++ .../src/airflow/ui/openapi-gen/requests/types.gen.ts | 4 ++++ .../core_api/routes/public/test_task_instances.py | 12 ++++++++++++ 10 files changed, 51 insertions(+), 10 deletions(-) diff --git a/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml b/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml index 2e064fa35a6a9..91952c822f795 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml +++ b/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml @@ -6609,6 +6609,18 @@ paths: title: Dag Id Pattern description: "SQL LIKE expression \u2014 use `%` / `_` wildcards (e.g. `%customer_%`).\ \ Regular expressions are **not** supported." + - name: run_id_pattern + in: query + required: false + schema: + anyOf: + - type: string + - type: 'null' + description: "SQL LIKE expression \u2014 use `%` / `_` wildcards (e.g. `%customer_%`).\ + \ Regular expressions are **not** supported." + title: Run Id Pattern + description: "SQL LIKE expression \u2014 use `%` / `_` wildcards (e.g. `%customer_%`).\ + \ Regular expressions are **not** supported." - name: state in: query required: false diff --git a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/task_instances.py b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/task_instances.py index e0e730399ad9b..77038d48154e6 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/task_instances.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/task_instances.py @@ -425,6 +425,7 @@ def get_task_instances( duration_range: Annotated[RangeFilter, Depends(float_range_filter_factory("duration", TI))], task_display_name_pattern: QueryTITaskDisplayNamePatternSearch, dag_id_pattern: Annotated[_SearchParam, Depends(search_param_factory(TI.dag_id, "dag_id_pattern"))], + run_id_pattern: Annotated[_SearchParam, Depends(search_param_factory(TI.run_id, "run_id_pattern"))], state: QueryTIStateFilter, pool: QueryTIPoolFilter, pool_name_pattern: QueryTIPoolNamePatternSearch, @@ -510,6 +511,7 @@ def get_task_instances( task_id, task_display_name_pattern, dag_id_pattern, + run_id_pattern, version_number, readable_ti_filter, try_number, diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts b/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts index e1ca849b1b5f6..22eb5638d3c58 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts @@ -474,7 +474,7 @@ export const UseTaskInstanceServiceGetMappedTaskInstanceKeyFn = ({ dagId, dagRun export type TaskInstanceServiceGetTaskInstancesDefaultResponse = Awaited>; export type TaskInstanceServiceGetTaskInstancesQueryResult = UseQueryResult; export const useTaskInstanceServiceGetTaskInstancesKey = "TaskInstanceServiceGetTaskInstances"; -export const UseTaskInstanceServiceGetTaskInstancesKeyFn = ({ dagId, dagIdPattern, dagRunId, durationGt, durationGte, durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, executor, limit, logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, mapIndex, offset, operator, operatorNamePattern, orderBy, pool, poolNamePattern, queue, queueNamePattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte, startDateGt, startDateGte, startDateLt, startDateLte, state, taskDisplayNamePattern, taskId, tryNumber, updatedAtGt, updatedAtGte, updatedAtLt, updatedAtLte, versionNumber }: { +export const UseTaskInstanceServiceGetTaskInstancesKeyFn = ({ dagId, dagIdPattern, dagRunId, durationGt, durationGte, durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, executor, limit, logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, mapIndex, offset, operator, operatorNamePattern, orderBy, pool, poolNamePattern, queue, queueNamePattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte, runIdPattern, startDateGt, startDateGte, startDateLt, startDateLte, state, taskDisplayNamePattern, taskId, tryNumber, updatedAtGt, updatedAtGte, updatedAtLt, updatedAtLte, versionNumber }: { dagId: string; dagIdPattern?: string; dagRunId: string; @@ -505,6 +505,7 @@ export const UseTaskInstanceServiceGetTaskInstancesKeyFn = ({ dagId, dagIdPatter runAfterGte?: string; runAfterLt?: string; runAfterLte?: string; + runIdPattern?: string; startDateGt?: string; startDateGte?: string; startDateLt?: string; @@ -518,7 +519,7 @@ export const UseTaskInstanceServiceGetTaskInstancesKeyFn = ({ dagId, dagIdPatter updatedAtLt?: string; updatedAtLte?: string; versionNumber?: number[]; -}, queryKey?: Array) => [useTaskInstanceServiceGetTaskInstancesKey, ...(queryKey ?? [{ dagId, dagIdPattern, dagRunId, durationGt, durationGte, durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, executor, limit, logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, mapIndex, offset, operator, operatorNamePattern, orderBy, pool, poolNamePattern, queue, queueNamePattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte, startDateGt, startDateGte, startDateLt, startDateLte, state, taskDisplayNamePattern, taskId, tryNumber, updatedAtGt, updatedAtGte, updatedAtLt, updatedAtLte, versionNumber }])]; +}, queryKey?: Array) => [useTaskInstanceServiceGetTaskInstancesKey, ...(queryKey ?? [{ dagId, dagIdPattern, dagRunId, durationGt, durationGte, durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, executor, limit, logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, mapIndex, offset, operator, operatorNamePattern, orderBy, pool, poolNamePattern, queue, queueNamePattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte, runIdPattern, startDateGt, startDateGte, startDateLt, startDateLte, state, taskDisplayNamePattern, taskId, tryNumber, updatedAtGt, updatedAtGte, updatedAtLt, updatedAtLte, versionNumber }])]; export type TaskInstanceServiceGetTaskInstanceTryDetailsDefaultResponse = Awaited>; export type TaskInstanceServiceGetTaskInstanceTryDetailsQueryResult = UseQueryResult; export const useTaskInstanceServiceGetTaskInstanceTryDetailsKey = "TaskInstanceServiceGetTaskInstanceTryDetails"; diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts b/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts index 995041a232e64..9ef3a526d1c80 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts @@ -926,6 +926,7 @@ export const ensureUseTaskInstanceServiceGetMappedTaskInstanceData = (queryClien * @param data.durationLt * @param data.taskDisplayNamePattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. * @param data.dagIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. +* @param data.runIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. * @param data.state * @param data.pool * @param data.poolNamePattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. @@ -943,7 +944,7 @@ export const ensureUseTaskInstanceServiceGetMappedTaskInstanceData = (queryClien * @returns TaskInstanceCollectionResponse Successful Response * @throws ApiError */ -export const ensureUseTaskInstanceServiceGetTaskInstancesData = (queryClient: QueryClient, { dagId, dagIdPattern, dagRunId, durationGt, durationGte, durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, executor, limit, logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, mapIndex, offset, operator, operatorNamePattern, orderBy, pool, poolNamePattern, queue, queueNamePattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte, startDateGt, startDateGte, startDateLt, startDateLte, state, taskDisplayNamePattern, taskId, tryNumber, updatedAtGt, updatedAtGte, updatedAtLt, updatedAtLte, versionNumber }: { +export const ensureUseTaskInstanceServiceGetTaskInstancesData = (queryClient: QueryClient, { dagId, dagIdPattern, dagRunId, durationGt, durationGte, durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, executor, limit, logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, mapIndex, offset, operator, operatorNamePattern, orderBy, pool, poolNamePattern, queue, queueNamePattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte, runIdPattern, startDateGt, startDateGte, startDateLt, startDateLte, state, taskDisplayNamePattern, taskId, tryNumber, updatedAtGt, updatedAtGte, updatedAtLt, updatedAtLte, versionNumber }: { dagId: string; dagIdPattern?: string; dagRunId: string; @@ -974,6 +975,7 @@ export const ensureUseTaskInstanceServiceGetTaskInstancesData = (queryClient: Qu runAfterGte?: string; runAfterLt?: string; runAfterLte?: string; + runIdPattern?: string; startDateGt?: string; startDateGte?: string; startDateLt?: string; @@ -987,7 +989,7 @@ export const ensureUseTaskInstanceServiceGetTaskInstancesData = (queryClient: Qu updatedAtLt?: string; updatedAtLte?: string; versionNumber?: number[]; -}) => queryClient.ensureQueryData({ queryKey: Common.UseTaskInstanceServiceGetTaskInstancesKeyFn({ dagId, dagIdPattern, dagRunId, durationGt, durationGte, durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, executor, limit, logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, mapIndex, offset, operator, operatorNamePattern, orderBy, pool, poolNamePattern, queue, queueNamePattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte, startDateGt, startDateGte, startDateLt, startDateLte, state, taskDisplayNamePattern, taskId, tryNumber, updatedAtGt, updatedAtGte, updatedAtLt, updatedAtLte, versionNumber }), queryFn: () => TaskInstanceService.getTaskInstances({ dagId, dagIdPattern, dagRunId, durationGt, durationGte, durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, executor, limit, logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, mapIndex, offset, operator, operatorNamePattern, orderBy, pool, poolNamePattern, queue, queueNamePattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte, startDateGt, startDateGte, startDateLt, startDateLte, state, taskDisplayNamePattern, taskId, tryNumber, updatedAtGt, updatedAtGte, updatedAtLt, updatedAtLte, versionNumber }) }); +}) => queryClient.ensureQueryData({ queryKey: Common.UseTaskInstanceServiceGetTaskInstancesKeyFn({ dagId, dagIdPattern, dagRunId, durationGt, durationGte, durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, executor, limit, logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, mapIndex, offset, operator, operatorNamePattern, orderBy, pool, poolNamePattern, queue, queueNamePattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte, runIdPattern, startDateGt, startDateGte, startDateLt, startDateLte, state, taskDisplayNamePattern, taskId, tryNumber, updatedAtGt, updatedAtGte, updatedAtLt, updatedAtLte, versionNumber }), queryFn: () => TaskInstanceService.getTaskInstances({ dagId, dagIdPattern, dagRunId, durationGt, durationGte, durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, executor, limit, logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, mapIndex, offset, operator, operatorNamePattern, orderBy, pool, poolNamePattern, queue, queueNamePattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte, runIdPattern, startDateGt, startDateGte, startDateLt, startDateLte, state, taskDisplayNamePattern, taskId, tryNumber, updatedAtGt, updatedAtGte, updatedAtLt, updatedAtLte, versionNumber }) }); /** * Get Task Instance Try Details * Get task instance details by try number. diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts b/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts index 0caf0a4fee426..4167272e47821 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts @@ -926,6 +926,7 @@ export const prefetchUseTaskInstanceServiceGetMappedTaskInstance = (queryClient: * @param data.durationLt * @param data.taskDisplayNamePattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. * @param data.dagIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. +* @param data.runIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. * @param data.state * @param data.pool * @param data.poolNamePattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. @@ -943,7 +944,7 @@ export const prefetchUseTaskInstanceServiceGetMappedTaskInstance = (queryClient: * @returns TaskInstanceCollectionResponse Successful Response * @throws ApiError */ -export const prefetchUseTaskInstanceServiceGetTaskInstances = (queryClient: QueryClient, { dagId, dagIdPattern, dagRunId, durationGt, durationGte, durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, executor, limit, logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, mapIndex, offset, operator, operatorNamePattern, orderBy, pool, poolNamePattern, queue, queueNamePattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte, startDateGt, startDateGte, startDateLt, startDateLte, state, taskDisplayNamePattern, taskId, tryNumber, updatedAtGt, updatedAtGte, updatedAtLt, updatedAtLte, versionNumber }: { +export const prefetchUseTaskInstanceServiceGetTaskInstances = (queryClient: QueryClient, { dagId, dagIdPattern, dagRunId, durationGt, durationGte, durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, executor, limit, logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, mapIndex, offset, operator, operatorNamePattern, orderBy, pool, poolNamePattern, queue, queueNamePattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte, runIdPattern, startDateGt, startDateGte, startDateLt, startDateLte, state, taskDisplayNamePattern, taskId, tryNumber, updatedAtGt, updatedAtGte, updatedAtLt, updatedAtLte, versionNumber }: { dagId: string; dagIdPattern?: string; dagRunId: string; @@ -974,6 +975,7 @@ export const prefetchUseTaskInstanceServiceGetTaskInstances = (queryClient: Quer runAfterGte?: string; runAfterLt?: string; runAfterLte?: string; + runIdPattern?: string; startDateGt?: string; startDateGte?: string; startDateLt?: string; @@ -987,7 +989,7 @@ export const prefetchUseTaskInstanceServiceGetTaskInstances = (queryClient: Quer updatedAtLt?: string; updatedAtLte?: string; versionNumber?: number[]; -}) => queryClient.prefetchQuery({ queryKey: Common.UseTaskInstanceServiceGetTaskInstancesKeyFn({ dagId, dagIdPattern, dagRunId, durationGt, durationGte, durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, executor, limit, logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, mapIndex, offset, operator, operatorNamePattern, orderBy, pool, poolNamePattern, queue, queueNamePattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte, startDateGt, startDateGte, startDateLt, startDateLte, state, taskDisplayNamePattern, taskId, tryNumber, updatedAtGt, updatedAtGte, updatedAtLt, updatedAtLte, versionNumber }), queryFn: () => TaskInstanceService.getTaskInstances({ dagId, dagIdPattern, dagRunId, durationGt, durationGte, durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, executor, limit, logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, mapIndex, offset, operator, operatorNamePattern, orderBy, pool, poolNamePattern, queue, queueNamePattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte, startDateGt, startDateGte, startDateLt, startDateLte, state, taskDisplayNamePattern, taskId, tryNumber, updatedAtGt, updatedAtGte, updatedAtLt, updatedAtLte, versionNumber }) }); +}) => queryClient.prefetchQuery({ queryKey: Common.UseTaskInstanceServiceGetTaskInstancesKeyFn({ dagId, dagIdPattern, dagRunId, durationGt, durationGte, durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, executor, limit, logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, mapIndex, offset, operator, operatorNamePattern, orderBy, pool, poolNamePattern, queue, queueNamePattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte, runIdPattern, startDateGt, startDateGte, startDateLt, startDateLte, state, taskDisplayNamePattern, taskId, tryNumber, updatedAtGt, updatedAtGte, updatedAtLt, updatedAtLte, versionNumber }), queryFn: () => TaskInstanceService.getTaskInstances({ dagId, dagIdPattern, dagRunId, durationGt, durationGte, durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, executor, limit, logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, mapIndex, offset, operator, operatorNamePattern, orderBy, pool, poolNamePattern, queue, queueNamePattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte, runIdPattern, startDateGt, startDateGte, startDateLt, startDateLte, state, taskDisplayNamePattern, taskId, tryNumber, updatedAtGt, updatedAtGte, updatedAtLt, updatedAtLte, versionNumber }) }); /** * Get Task Instance Try Details * Get task instance details by try number. diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts b/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts index a3af73a6c7f84..bd6f2a10463cf 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts @@ -926,6 +926,7 @@ export const useTaskInstanceServiceGetMappedTaskInstance = = unknown[]>({ dagId, dagIdPattern, dagRunId, durationGt, durationGte, durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, executor, limit, logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, mapIndex, offset, operator, operatorNamePattern, orderBy, pool, poolNamePattern, queue, queueNamePattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte, startDateGt, startDateGte, startDateLt, startDateLte, state, taskDisplayNamePattern, taskId, tryNumber, updatedAtGt, updatedAtGte, updatedAtLt, updatedAtLte, versionNumber }: { +export const useTaskInstanceServiceGetTaskInstances = = unknown[]>({ dagId, dagIdPattern, dagRunId, durationGt, durationGte, durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, executor, limit, logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, mapIndex, offset, operator, operatorNamePattern, orderBy, pool, poolNamePattern, queue, queueNamePattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte, runIdPattern, startDateGt, startDateGte, startDateLt, startDateLte, state, taskDisplayNamePattern, taskId, tryNumber, updatedAtGt, updatedAtGte, updatedAtLt, updatedAtLte, versionNumber }: { dagId: string; dagIdPattern?: string; dagRunId: string; @@ -974,6 +975,7 @@ export const useTaskInstanceServiceGetTaskInstances = , "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseTaskInstanceServiceGetTaskInstancesKeyFn({ dagId, dagIdPattern, dagRunId, durationGt, durationGte, durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, executor, limit, logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, mapIndex, offset, operator, operatorNamePattern, orderBy, pool, poolNamePattern, queue, queueNamePattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte, startDateGt, startDateGte, startDateLt, startDateLte, state, taskDisplayNamePattern, taskId, tryNumber, updatedAtGt, updatedAtGte, updatedAtLt, updatedAtLte, versionNumber }, queryKey), queryFn: () => TaskInstanceService.getTaskInstances({ dagId, dagIdPattern, dagRunId, durationGt, durationGte, durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, executor, limit, logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, mapIndex, offset, operator, operatorNamePattern, orderBy, pool, poolNamePattern, queue, queueNamePattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte, startDateGt, startDateGte, startDateLt, startDateLte, state, taskDisplayNamePattern, taskId, tryNumber, updatedAtGt, updatedAtGte, updatedAtLt, updatedAtLte, versionNumber }) as TData, ...options }); +}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseTaskInstanceServiceGetTaskInstancesKeyFn({ dagId, dagIdPattern, dagRunId, durationGt, durationGte, durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, executor, limit, logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, mapIndex, offset, operator, operatorNamePattern, orderBy, pool, poolNamePattern, queue, queueNamePattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte, runIdPattern, startDateGt, startDateGte, startDateLt, startDateLte, state, taskDisplayNamePattern, taskId, tryNumber, updatedAtGt, updatedAtGte, updatedAtLt, updatedAtLte, versionNumber }, queryKey), queryFn: () => TaskInstanceService.getTaskInstances({ dagId, dagIdPattern, dagRunId, durationGt, durationGte, durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, executor, limit, logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, mapIndex, offset, operator, operatorNamePattern, orderBy, pool, poolNamePattern, queue, queueNamePattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte, runIdPattern, startDateGt, startDateGte, startDateLt, startDateLte, state, taskDisplayNamePattern, taskId, tryNumber, updatedAtGt, updatedAtGte, updatedAtLt, updatedAtLte, versionNumber }) as TData, ...options }); /** * Get Task Instance Try Details * Get task instance details by try number. diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts b/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts index e8a53657dd175..d6e86d08c642b 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts @@ -926,6 +926,7 @@ export const useTaskInstanceServiceGetMappedTaskInstanceSuspense = = unknown[]>({ dagId, dagIdPattern, dagRunId, durationGt, durationGte, durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, executor, limit, logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, mapIndex, offset, operator, operatorNamePattern, orderBy, pool, poolNamePattern, queue, queueNamePattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte, startDateGt, startDateGte, startDateLt, startDateLte, state, taskDisplayNamePattern, taskId, tryNumber, updatedAtGt, updatedAtGte, updatedAtLt, updatedAtLte, versionNumber }: { +export const useTaskInstanceServiceGetTaskInstancesSuspense = = unknown[]>({ dagId, dagIdPattern, dagRunId, durationGt, durationGte, durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, executor, limit, logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, mapIndex, offset, operator, operatorNamePattern, orderBy, pool, poolNamePattern, queue, queueNamePattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte, runIdPattern, startDateGt, startDateGte, startDateLt, startDateLte, state, taskDisplayNamePattern, taskId, tryNumber, updatedAtGt, updatedAtGte, updatedAtLt, updatedAtLte, versionNumber }: { dagId: string; dagIdPattern?: string; dagRunId: string; @@ -974,6 +975,7 @@ export const useTaskInstanceServiceGetTaskInstancesSuspense = , "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseTaskInstanceServiceGetTaskInstancesKeyFn({ dagId, dagIdPattern, dagRunId, durationGt, durationGte, durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, executor, limit, logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, mapIndex, offset, operator, operatorNamePattern, orderBy, pool, poolNamePattern, queue, queueNamePattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte, startDateGt, startDateGte, startDateLt, startDateLte, state, taskDisplayNamePattern, taskId, tryNumber, updatedAtGt, updatedAtGte, updatedAtLt, updatedAtLte, versionNumber }, queryKey), queryFn: () => TaskInstanceService.getTaskInstances({ dagId, dagIdPattern, dagRunId, durationGt, durationGte, durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, executor, limit, logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, mapIndex, offset, operator, operatorNamePattern, orderBy, pool, poolNamePattern, queue, queueNamePattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte, startDateGt, startDateGte, startDateLt, startDateLte, state, taskDisplayNamePattern, taskId, tryNumber, updatedAtGt, updatedAtGte, updatedAtLt, updatedAtLte, versionNumber }) as TData, ...options }); +}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseTaskInstanceServiceGetTaskInstancesKeyFn({ dagId, dagIdPattern, dagRunId, durationGt, durationGte, durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, executor, limit, logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, mapIndex, offset, operator, operatorNamePattern, orderBy, pool, poolNamePattern, queue, queueNamePattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte, runIdPattern, startDateGt, startDateGte, startDateLt, startDateLte, state, taskDisplayNamePattern, taskId, tryNumber, updatedAtGt, updatedAtGte, updatedAtLt, updatedAtLte, versionNumber }, queryKey), queryFn: () => TaskInstanceService.getTaskInstances({ dagId, dagIdPattern, dagRunId, durationGt, durationGte, durationLt, durationLte, endDateGt, endDateGte, endDateLt, endDateLte, executor, limit, logicalDateGt, logicalDateGte, logicalDateLt, logicalDateLte, mapIndex, offset, operator, operatorNamePattern, orderBy, pool, poolNamePattern, queue, queueNamePattern, runAfterGt, runAfterGte, runAfterLt, runAfterLte, runIdPattern, startDateGt, startDateGte, startDateLt, startDateLte, state, taskDisplayNamePattern, taskId, tryNumber, updatedAtGt, updatedAtGte, updatedAtLt, updatedAtLte, versionNumber }) as TData, ...options }); /** * Get Task Instance Try Details * Get task instance details by try number. diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts b/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts index 808f54ab9ad19..66091a2b06c4c 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts @@ -2336,6 +2336,7 @@ export class TaskInstanceService { * @param data.durationLt * @param data.taskDisplayNamePattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. * @param data.dagIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. + * @param data.runIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. * @param data.state * @param data.pool * @param data.poolNamePattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. @@ -2389,6 +2390,7 @@ export class TaskInstanceService { duration_lt: data.durationLt, task_display_name_pattern: data.taskDisplayNamePattern, dag_id_pattern: data.dagIdPattern, + run_id_pattern: data.runIdPattern, state: data.state, pool: data.pool, pool_name_pattern: data.poolNamePattern, diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts b/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts index 57c5d50b3db5c..797df33fa0c66 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts @@ -2883,6 +2883,10 @@ export type GetTaskInstancesData = { runAfterGte?: string | null; runAfterLt?: string | null; runAfterLte?: string | null; + /** + * SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. + */ + runIdPattern?: string | null; startDateGt?: string | null; startDateGte?: string | null; startDateLt?: string | null; diff --git a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_task_instances.py b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_task_instances.py index 5c6d8db50a4ba..6e25fa4723354 100644 --- a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_task_instances.py +++ b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_task_instances.py @@ -1325,6 +1325,18 @@ class TestGetTaskInstances(TestTaskInstanceEndpoint): 3, id="test map_index filter", ), + pytest.param( + [ + {}, + ], + True, + ("/dags/~/dagRuns/~/taskInstances"), + {"run_id_pattern": "TEST_DAG_"}, + 1,# apart from the TIs in the fixture, we also get one from + # the create_task_instances method + 3, + id="test run_id_pattern filter", + ), pytest.param( "dag_id_pattern_test", # Special marker for multi-DAG test False, From b18550f2e57a00e671b84983aacb8cb3006013ea Mon Sep 17 00:00:00 2001 From: seanyu Date: Sun, 16 Nov 2025 13:25:48 +0800 Subject: [PATCH 7/9] fix format --- .../api_fastapi/core_api/routes/public/test_task_instances.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_task_instances.py b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_task_instances.py index 6e25fa4723354..1c16e32406c25 100644 --- a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_task_instances.py +++ b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_task_instances.py @@ -1328,11 +1328,11 @@ class TestGetTaskInstances(TestTaskInstanceEndpoint): pytest.param( [ {}, - ], + ], True, ("/dags/~/dagRuns/~/taskInstances"), {"run_id_pattern": "TEST_DAG_"}, - 1,# apart from the TIs in the fixture, we also get one from + 1, # apart from the TIs in the fixture, we also get one from # the create_task_instances method 3, id="test run_id_pattern filter", From b0d09749d5788e874b36eaee315f178b55dae7d2 Mon Sep 17 00:00:00 2001 From: seanyu Date: Tue, 18 Nov 2025 15:38:20 +0800 Subject: [PATCH 8/9] change run_id filter to name pattern filter --- .../airflow/ui/src/pages/TaskInstances/TaskInstances.tsx | 7 ++++--- .../ui/src/pages/TaskInstances/TaskInstancesFilter.tsx | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsx b/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsx index 2a28b1b91abde..f4e0e14aca6c5 100644 --- a/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsx +++ b/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsx @@ -58,7 +58,7 @@ const { OPERATOR_NAME_PATTERN: OPERATOR_NAME_PATTERN_PARAM, POOL_NAME_PATTERN: POOL_NAME_PATTERN_PARAM, QUEUE_NAME_PATTERN: QUEUE_NAME_PATTERN_PARAM, - RUN_ID: RUN_ID_PARAM, + RUN_ID_PATTERN: RUN_ID_PATTERN_PARAM, START_DATE: START_DATE_PARAM, TASK_STATE: STATE_PARAM, TRY_NUMBER: TRY_NUMBER_PARAM, @@ -252,7 +252,7 @@ export const TaskInstances = () => { const queueNamePattern = searchParams.get(QUEUE_NAME_PATTERN_PARAM); const operatorNamePattern = searchParams.get(OPERATOR_NAME_PATTERN_PARAM); const filteredDagIdPattern = searchParams.get(DAG_ID_PATTERN_PARAM); - const filteredRunId = searchParams.get(RUN_ID_PARAM); + const filteredRunId = searchParams.get(RUN_ID_PATTERN_PARAM); const hasFilteredState = filteredState.length > 0; const taskDisplayNamePattern = searchParams.get(NAME_PATTERN_PARAM); @@ -262,7 +262,7 @@ export const TaskInstances = () => { { dagId: dagId ?? "~", dagIdPattern: filteredDagIdPattern ?? undefined, - dagRunId: runId ?? filteredRunId ?? "~", + dagRunId: runId ?? "~", durationGte: durationGte !== null && durationGte !== "" ? Number(durationGte) : undefined, durationLte: durationLte !== null && durationLte !== "" ? Number(durationLte) : undefined, endDateLte: endDate ?? undefined, @@ -275,6 +275,7 @@ export const TaskInstances = () => { orderBy, poolNamePattern: poolNamePattern ?? undefined, queueNamePattern: queueNamePattern ?? undefined, + runIdPattern: filteredRunId ?? undefined, startDateGte: startDate ?? undefined, state: hasFilteredState ? filteredState : undefined, taskDisplayNamePattern: groupId ?? taskDisplayNamePattern ?? undefined, diff --git a/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstancesFilter.tsx b/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstancesFilter.tsx index 56ab3e8dc4891..0436897fbb310 100644 --- a/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstancesFilter.tsx +++ b/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstancesFilter.tsx @@ -37,7 +37,7 @@ const { OPERATOR_NAME_PATTERN: OPERATOR_NAME_PATTERN_PARAM, POOL_NAME_PATTERN: POOL_NAME_PATTERN_PARAM, QUEUE_NAME_PATTERN: QUEUE_NAME_PATTERN_PARAM, - RUN_ID: RUN_ID_PARAM, + RUN_ID_PATTERN: RUN_ID_PATTERN_PARAM, START_DATE: START_DATE_PARAM, TASK_STATE: STATE_PARAM, TRY_NUMBER: TRY_NUMBER_PARAM, @@ -64,7 +64,7 @@ export const TaskInstancesFilter = () => { ]; if (runId === undefined) { - keys.unshift(RUN_ID_PARAM as FilterableSearchParamsKeys); + keys.unshift(RUN_ID_PATTERN_PARAM as FilterableSearchParamsKeys); } if (dagId === undefined) { From 8084ffb2aaf3e5be7596b8aac1a8c4acd3fd00c5 Mon Sep 17 00:00:00 2001 From: seanyu Date: Fri, 21 Nov 2025 14:12:54 +0800 Subject: [PATCH 9/9] merge date range picker --- .../src/airflow/ui/src/constants/filterConfigs.tsx | 4 ++-- .../src/pages/TaskInstances/TaskInstancesFilter.tsx | 12 ++++-------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/airflow-core/src/airflow/ui/src/constants/filterConfigs.tsx b/airflow-core/src/airflow/ui/src/constants/filterConfigs.tsx index 9baa23512747e..a2308e2869f3f 100644 --- a/airflow-core/src/airflow/ui/src/constants/filterConfigs.tsx +++ b/airflow-core/src/airflow/ui/src/constants/filterConfigs.tsx @@ -54,13 +54,13 @@ export enum FilterTypes { } export const useFilterConfigs = () => { - const { t: translate } = useTranslation(["browse", "common", "admin", "hitl"]); + const { t: translate } = useTranslation(["browse", "common", "components", "admin", "hitl"]); const filterConfigMap = { [SearchParamsKeys.ASSET_EVENT_DATE_RANGE]: { endKey: SearchParamsKeys.END_DATE, icon: , - label: translate("common:logicalDate"), + label: translate("components:backfill.dateRange"), startKey: SearchParamsKeys.START_DATE, type: FilterTypes.DATERANGE, }, diff --git a/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstancesFilter.tsx b/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstancesFilter.tsx index 0436897fbb310..ccb4ba91f993f 100644 --- a/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstancesFilter.tsx +++ b/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstancesFilter.tsx @@ -25,20 +25,18 @@ import { SearchParamsKeys, type SearchParamsKeysType } from "src/constants/searc import { useFiltersHandler, type FilterableSearchParamsKeys } from "src/utils"; const { + ASSET_EVENT_DATE_RANGE: ASSET_EVENT_DATE_RANGE_PARAM, DAG_ID_PATTERN: DAG_ID_PATTERN_PARAM, DAG_VERSION: DAG_VERSION_PARAM, DURATION_GTE: DURATION_GTE_PARAM, DURATION_LTE: DURATION_LTE_PARAM, - END_DATE: END_DATE_PARAM, - LOGICAL_DATE_GTE: LOGICAL_DATE_GTE_PARAM, - LOGICAL_DATE_LTE: LOGICAL_DATE_LTE_PARAM, + LOGICAL_DATE_RANGE: LOGICAL_DATE_RANGE_PARAM, MAP_INDEX: MAP_INDEX_PARAM, NAME_PATTERN: NAME_PATTERN_PARAM, OPERATOR_NAME_PATTERN: OPERATOR_NAME_PATTERN_PARAM, POOL_NAME_PATTERN: POOL_NAME_PATTERN_PARAM, QUEUE_NAME_PATTERN: QUEUE_NAME_PATTERN_PARAM, RUN_ID_PATTERN: RUN_ID_PATTERN_PARAM, - START_DATE: START_DATE_PARAM, TASK_STATE: STATE_PARAM, TRY_NUMBER: TRY_NUMBER_PARAM, }: SearchParamsKeysType = SearchParamsKeys; @@ -48,10 +46,8 @@ export const TaskInstancesFilter = () => { const paramKeys = useMemo((): Array => { const keys: Array = [ NAME_PATTERN_PARAM as FilterableSearchParamsKeys, - LOGICAL_DATE_GTE_PARAM as FilterableSearchParamsKeys, - LOGICAL_DATE_LTE_PARAM as FilterableSearchParamsKeys, - START_DATE_PARAM as FilterableSearchParamsKeys, - END_DATE_PARAM as FilterableSearchParamsKeys, + LOGICAL_DATE_RANGE_PARAM as FilterableSearchParamsKeys, + ASSET_EVENT_DATE_RANGE_PARAM as FilterableSearchParamsKeys, DURATION_GTE_PARAM as FilterableSearchParamsKeys, DURATION_LTE_PARAM as FilterableSearchParamsKeys, TRY_NUMBER_PARAM as FilterableSearchParamsKeys,