This is an automated email from the ASF dual-hosted git repository.
jscheffl 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 9fabe619eb3 refactor(ui): replace hardcoded query parameter strings
with SearchParamsKeys constants (#55218)
9fabe619eb3 is described below
commit 9fabe619eb3c818b98600fca5a9f49b7ea457754
Author: Dheeraj Turaga <[email protected]>
AuthorDate: Wed Sep 3 09:48:30 2025 -0500
refactor(ui): replace hardcoded query parameter strings with
SearchParamsKeys constants (#55218)
- Replace all hardcoded query parameter strings in redirects and navigation
with constants from SearchParamsKeys enum
- Improves maintainability by centralizing query parameter names in
constants/searchParams.ts
- Prevents typos and ensures consistency across the UI codebase
---
airflow-core/src/airflow/ui/src/components/NeedsReviewBadge.tsx | 3 ++-
airflow-core/src/airflow/ui/src/components/PoolBar.tsx | 7 ++++++-
airflow-core/src/airflow/ui/src/pages/Dag/Overview/Overview.tsx | 5 +++--
airflow-core/src/airflow/ui/src/pages/DagsList/DagTags.tsx | 3 ++-
.../ui/src/pages/Dashboard/HistoricalMetrics/DagRunMetrics.tsx | 3 ++-
.../ui/src/pages/Dashboard/HistoricalMetrics/MetricSection.tsx | 7 +++++--
.../src/pages/Dashboard/HistoricalMetrics/TaskInstanceMetrics.tsx | 3 ++-
airflow-core/src/airflow/ui/src/pages/Run/Header.tsx | 3 ++-
airflow-core/src/airflow/ui/src/pages/Task/Overview/Overview.tsx | 3 ++-
airflow-core/src/airflow/ui/src/pages/TaskInstance/Details.tsx | 7 ++++---
10 files changed, 30 insertions(+), 14 deletions(-)
diff --git a/airflow-core/src/airflow/ui/src/components/NeedsReviewBadge.tsx
b/airflow-core/src/airflow/ui/src/components/NeedsReviewBadge.tsx
index c422ff0fcf2..5b7bd3f3899 100644
--- a/airflow-core/src/airflow/ui/src/components/NeedsReviewBadge.tsx
+++ b/airflow-core/src/airflow/ui/src/components/NeedsReviewBadge.tsx
@@ -23,6 +23,7 @@ import { Link as RouterLink } from "react-router-dom";
import type { HITLDetail } from "openapi/requests/types.gen";
import { StateBadge } from "src/components/StateBadge";
import { Tooltip } from "src/components/ui";
+import { SearchParamsKeys } from "src/constants/searchParams";
type Props = {
readonly dagId: string;
@@ -38,7 +39,7 @@ export const NeedsReviewBadge = ({ dagId, pendingActions }:
Props) => {
return (
<Tooltip content={translate("requiredActionCount", { count:
pendingActions.length })}>
- <RouterLink
to={`/dags/${dagId}/required_actions?response_received=false`}>
+ <RouterLink
to={`/dags/${dagId}/required_actions?${SearchParamsKeys.RESPONSE_RECEIVED}=false`}>
<StateBadge colorPalette="deferred" fontSize="md" variant="solid">
<LuUserRoundPen />
{pendingActions.length}
diff --git a/airflow-core/src/airflow/ui/src/components/PoolBar.tsx
b/airflow-core/src/airflow/ui/src/components/PoolBar.tsx
index a0cfdb700e8..4eec20af141 100644
--- a/airflow-core/src/airflow/ui/src/components/PoolBar.tsx
+++ b/airflow-core/src/airflow/ui/src/components/PoolBar.tsx
@@ -22,6 +22,7 @@ import { Link as RouterLink } from "react-router-dom";
import type { PoolResponse } from "openapi/requests/types.gen";
import { Tooltip } from "src/components/ui";
+import { SearchParamsKeys } from "src/constants/searchParams";
import { type Slots, slotConfigs } from "src/utils/slots";
export const PoolBar = ({
@@ -69,7 +70,11 @@ export const PoolBar = ({
return color !== "success" && "name" in pool ? (
<Link asChild display="flex" flex={flexValue} key={key}>
- <RouterLink
to={`/task_instances?state=${color}&pool=${pool.name}`}>{poolContent}</RouterLink>
+ <RouterLink
+
to={`/task_instances?${SearchParamsKeys.STATE}=${color}&${SearchParamsKeys.POOL}=${pool.name}`}
+ >
+ {poolContent}
+ </RouterLink>
</Link>
) : (
<Box display="flex" flex={flexValue} key={key}>
diff --git a/airflow-core/src/airflow/ui/src/pages/Dag/Overview/Overview.tsx
b/airflow-core/src/airflow/ui/src/pages/Dag/Overview/Overview.tsx
index dfb13ef118c..8cebcc4ba0b 100644
--- a/airflow-core/src/airflow/ui/src/pages/Dag/Overview/Overview.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Dag/Overview/Overview.tsx
@@ -33,6 +33,7 @@ import { DurationChart } from "src/components/DurationChart";
import { NeedsReviewButton } from "src/components/NeedsReviewButton";
import TimeRangeSelector from "src/components/TimeRangeSelector";
import { TrendCountButton } from "src/components/TrendCountButton";
+import { SearchParamsKeys } from "src/constants/searchParams";
import { useGridRuns } from "src/queries/useGridRuns.ts";
const FailedLogs = lazy(() => import("./FailedLogs"));
@@ -98,7 +99,7 @@ export const Overview = () => {
label={translate("overview.buttons.failedTask", { count:
failedTasks?.total_entries ?? 0 })}
route={{
pathname: "tasks",
- search: "state=failed",
+ search: `${SearchParamsKeys.STATE}=failed`,
}}
startDate={startDate}
/>
@@ -113,7 +114,7 @@ export const Overview = () => {
label={translate("overview.buttons.failedRun", { count:
failedRuns?.total_entries ?? 0 })}
route={{
pathname: "runs",
- search: "state=failed",
+ search: `${SearchParamsKeys.STATE}=failed`,
}}
startDate={startDate}
/>
diff --git a/airflow-core/src/airflow/ui/src/pages/DagsList/DagTags.tsx
b/airflow-core/src/airflow/ui/src/pages/DagsList/DagTags.tsx
index f1977bdeec5..6f28113236f 100644
--- a/airflow-core/src/airflow/ui/src/pages/DagsList/DagTags.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/DagsList/DagTags.tsx
@@ -21,6 +21,7 @@ import { Link as RouterLink } from "react-router-dom";
import type { DagTagResponse } from "openapi/requests/types.gen";
import { LimitedItemsList } from "src/components/LimitedItemsList";
+import { SearchParamsKeys } from "src/constants/searchParams";
const MAX_TAGS = 3;
@@ -34,7 +35,7 @@ export const DagTags = ({ hideIcon = false, tags }: Props) =>
(
icon={hideIcon ? undefined : <FiTag data-testid="dag-tag" />}
interactive
items={tags.map(({ name }) => (
- <RouterLink key={name} to={`/dags?tags=${name}`}>
+ <RouterLink key={name} to={`/dags?${SearchParamsKeys.TAGS}=${name}`}>
{name}
</RouterLink>
))}
diff --git
a/airflow-core/src/airflow/ui/src/pages/Dashboard/HistoricalMetrics/DagRunMetrics.tsx
b/airflow-core/src/airflow/ui/src/pages/Dashboard/HistoricalMetrics/DagRunMetrics.tsx
index d3a8e6c5bba..6c65dffbacc 100644
---
a/airflow-core/src/airflow/ui/src/pages/Dashboard/HistoricalMetrics/DagRunMetrics.tsx
+++
b/airflow-core/src/airflow/ui/src/pages/Dashboard/HistoricalMetrics/DagRunMetrics.tsx
@@ -23,6 +23,7 @@ import { FiBarChart } from "react-icons/fi";
import { Link as RouterLink } from "react-router-dom";
import { StateBadge } from "src/components/StateBadge";
+import { SearchParamsKeys } from "src/constants/searchParams";
import { MetricSection } from "./MetricSection";
@@ -42,7 +43,7 @@ export const DagRunMetrics = ({ dagRunStates, endDate,
startDate, total }: DagRu
<Box borderRadius={5} borderWidth={1} p={4}>
<HStack>
<RouterLink
- to={`/dag_runs?start_date=${startDate}${endDate === undefined ? "" :
`&end_date=${endDate}`}`}
+ to={`/dag_runs?${SearchParamsKeys.START_DATE}=${startDate}${endDate
=== undefined ? "" : `&${SearchParamsKeys.END_DATE}=${endDate}`}`}
>
<StateBadge colorPalette="blue" fontSize="md" variant="solid">
<FiBarChart />
diff --git
a/airflow-core/src/airflow/ui/src/pages/Dashboard/HistoricalMetrics/MetricSection.tsx
b/airflow-core/src/airflow/ui/src/pages/Dashboard/HistoricalMetrics/MetricSection.tsx
index 0057b2a1524..48c3fdd4e30 100644
---
a/airflow-core/src/airflow/ui/src/pages/Dashboard/HistoricalMetrics/MetricSection.tsx
+++
b/airflow-core/src/airflow/ui/src/pages/Dashboard/HistoricalMetrics/MetricSection.tsx
@@ -22,6 +22,7 @@ import { Link as RouterLink } from "react-router-dom";
import type { TaskInstanceStateCount } from "openapi/requests/types.gen";
import { StateBadge } from "src/components/StateBadge";
+import { SearchParamsKeys } from "src/constants/searchParams";
const BAR_WIDTH = 100;
const BAR_HEIGHT = 5;
@@ -42,11 +43,13 @@ export const MetricSection = ({ endDate, kind, runs,
startDate, state, total }:
const stateWidth = total === 0 ? 0 : (runs / total) * BAR_WIDTH;
const remainingWidth = BAR_WIDTH - stateWidth;
- const searchParams = new
URLSearchParams(`?state=${state}&start_date=${startDate}`);
+ const searchParams = new URLSearchParams(
+
`?${SearchParamsKeys.STATE}=${state}&${SearchParamsKeys.START_DATE}=${startDate}`,
+ );
const { t: translate } = useTranslation();
if (endDate !== undefined) {
- searchParams.append("end_date", endDate);
+ searchParams.append(SearchParamsKeys.END_DATE, endDate);
}
return (
diff --git
a/airflow-core/src/airflow/ui/src/pages/Dashboard/HistoricalMetrics/TaskInstanceMetrics.tsx
b/airflow-core/src/airflow/ui/src/pages/Dashboard/HistoricalMetrics/TaskInstanceMetrics.tsx
index 172a0b48879..4037c292e3f 100644
---
a/airflow-core/src/airflow/ui/src/pages/Dashboard/HistoricalMetrics/TaskInstanceMetrics.tsx
+++
b/airflow-core/src/airflow/ui/src/pages/Dashboard/HistoricalMetrics/TaskInstanceMetrics.tsx
@@ -23,6 +23,7 @@ import { MdOutlineTask } from "react-icons/md";
import { Link as RouterLink } from "react-router-dom";
import { StateBadge } from "src/components/StateBadge";
+import { SearchParamsKeys } from "src/constants/searchParams";
import { MetricSection } from "./MetricSection";
@@ -61,7 +62,7 @@ export const TaskInstanceMetrics = ({
<Box borderRadius={5} borderWidth={1} mt={2} p={4}>
<HStack>
<RouterLink
- to={`/task_instances?start_date=${startDate}${endDate === undefined
? "" : `&end_date=${endDate}`}`}
+
to={`/task_instances?${SearchParamsKeys.START_DATE}=${startDate}${endDate ===
undefined ? "" : `&${SearchParamsKeys.END_DATE}=${endDate}`}`}
>
<StateBadge colorPalette="blue" fontSize="md" variant="solid">
<MdOutlineTask />
diff --git a/airflow-core/src/airflow/ui/src/pages/Run/Header.tsx
b/airflow-core/src/airflow/ui/src/pages/Run/Header.tsx
index 83199ca775f..dff8a604919 100644
--- a/airflow-core/src/airflow/ui/src/pages/Run/Header.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Run/Header.tsx
@@ -31,6 +31,7 @@ import { LimitedItemsList } from
"src/components/LimitedItemsList";
import { MarkRunAsButton } from "src/components/MarkAs";
import { RunTypeIcon } from "src/components/RunTypeIcon";
import Time from "src/components/Time";
+import { SearchParamsKeys } from "src/constants/searchParams";
import { usePatchDagRun } from "src/queries/usePatchDagRun";
import { getDuration, useContainerWidth } from "src/utils";
@@ -123,7 +124,7 @@ export const Header = ({
value: (
<Link asChild color="fg.info">
<RouterLink
-
to={`/dag_runs?triggering_user_name_pattern=${encodeURIComponent(dagRun.triggering_user_name)}`}
+
to={`/dag_runs?${SearchParamsKeys.TRIGGERING_USER_NAME_PATTERN}=${encodeURIComponent(dagRun.triggering_user_name)}`}
>
<Text>{dagRun.triggering_user_name}</Text>
</RouterLink>
diff --git a/airflow-core/src/airflow/ui/src/pages/Task/Overview/Overview.tsx
b/airflow-core/src/airflow/ui/src/pages/Task/Overview/Overview.tsx
index 86a7ca56e5e..3ee154c1392 100644
--- a/airflow-core/src/airflow/ui/src/pages/Task/Overview/Overview.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Task/Overview/Overview.tsx
@@ -27,6 +27,7 @@ import { DurationChart } from "src/components/DurationChart";
import { NeedsReviewButton } from "src/components/NeedsReviewButton";
import TimeRangeSelector from "src/components/TimeRangeSelector";
import { TrendCountButton } from "src/components/TrendCountButton";
+import { SearchParamsKeys } from "src/constants/searchParams";
import { isStatePending, useAutoRefresh } from "src/utils";
const defaultHour = "24";
@@ -95,7 +96,7 @@ export const Overview = () => {
})}
route={{
pathname: "task_instances",
- search: "state=failed",
+ search: `${SearchParamsKeys.STATE}=failed`,
}}
startDate={startDate}
/>
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 a424ec0a063..15b35e4b5b4 100644
--- a/airflow-core/src/airflow/ui/src/pages/TaskInstance/Details.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/TaskInstance/Details.tsx
@@ -29,6 +29,7 @@ import { StateBadge } from "src/components/StateBadge";
import { TaskTrySelect } from "src/components/TaskTrySelect";
import Time from "src/components/Time";
import { ClipboardRoot, ClipboardIconButton } from "src/components/ui";
+import { SearchParamsKeys } from "src/constants/searchParams";
import { getDuration, useAutoRefresh, isStatePending } from "src/utils";
import { BlockingDeps } from "./BlockingDeps";
@@ -40,7 +41,7 @@ export const Details = () => {
const { dagId = "", mapIndex = "-1", runId = "", taskId = "" } = useParams();
const [searchParams, setSearchParams] = useSearchParams();
- const tryNumberParam = searchParams.get("try_number");
+ const tryNumberParam = searchParams.get(SearchParamsKeys.TRY_NUMBER);
const { data: taskInstance } = useTaskInstanceServiceGetMappedTaskInstance({
dagId,
@@ -51,9 +52,9 @@ export const Details = () => {
const onSelectTryNumber = (newTryNumber: number) => {
if (newTryNumber === taskInstance?.try_number) {
- searchParams.delete("try_number");
+ searchParams.delete(SearchParamsKeys.TRY_NUMBER);
} else {
- searchParams.set("try_number", newTryNumber.toString());
+ searchParams.set(SearchParamsKeys.TRY_NUMBER, newTryNumber.toString());
}
setSearchParams(searchParams);
};