This is an automated email from the ASF dual-hosted git repository.

bbovenzi pushed a commit to branch v3-2-test
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/v3-2-test by this push:
     new b2b3ce26070 [v3-2-test] UI: Filter DagVersionSelect options based on 
selected DagRun (#64736) (#64771)
b2b3ce26070 is described below

commit b2b3ce2607088ec5c11356ac5e271cb80fd8b6bb
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Mon Apr 6 13:08:57 2026 -0400

    [v3-2-test] UI: Filter DagVersionSelect options based on selected DagRun 
(#64736) (#64771)
    
    * UI: Filter DagVersionSelect options based on selected DagRun
    
    * fix: remove trailing blank line in test file
    
    ---------
    (cherry picked from commit 8e1f6c457c38c8547b04cc5a4b7cb6c634a48783)
    
    Co-authored-by: Daniel Seo <[email protected]>
    Co-authored-by: hseo36 <[email protected]>
---
 .../ui/src/components/DagVersionSelect.test.tsx    | 120 +++++++++++++++++++++
 .../airflow/ui/src/components/DagVersionSelect.tsx |  23 +++-
 2 files changed, 138 insertions(+), 5 deletions(-)

diff --git 
a/airflow-core/src/airflow/ui/src/components/DagVersionSelect.test.tsx 
b/airflow-core/src/airflow/ui/src/components/DagVersionSelect.test.tsx
new file mode 100644
index 00000000000..38b0332252a
--- /dev/null
+++ b/airflow-core/src/airflow/ui/src/components/DagVersionSelect.test.tsx
@@ -0,0 +1,120 @@
+/*!
+ * 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 { render } from "@testing-library/react";
+import { describe, expect, it, vi } from "vitest";
+
+import { Wrapper } from "src/utils/Wrapper";
+
+import { DagVersionSelect } from "./DagVersionSelect";
+
+const dagVersionV1 = {
+  bundle_name: "dags-folder",
+  bundle_version: null,
+  created_at: "2025-01-01T00:00:00Z",
+  dag_id: "test_dag",
+  version_number: 1,
+};
+const dagVersionV2 = {
+  bundle_name: "dags-folder",
+  bundle_version: null,
+  created_at: "2025-01-02T00:00:00Z",
+  dag_id: "test_dag",
+  version_number: 2,
+};
+const dagVersionV3 = {
+  bundle_name: "dags-folder",
+  bundle_version: null,
+  created_at: "2025-01-03T00:00:00Z",
+  dag_id: "test_dag",
+  version_number: 3,
+};
+
+const allVersions = [dagVersionV3, dagVersionV2, dagVersionV1];
+
+let mockParams: Record<string, string> = { dagId: "test_dag" };
+
+vi.mock("react-router-dom", async () => {
+  const actual = await vi.importActual("react-router-dom");
+
+  return {
+    ...actual,
+    useParams: () => mockParams,
+  };
+});
+
+vi.mock("openapi/queries", () => ({
+  useDagRunServiceGetDagRun: vi.fn(() => ({
+    data: undefined,
+    isLoading: false,
+  })),
+  useDagVersionServiceGetDagVersions: vi.fn(() => ({
+    data: { dag_versions: allVersions, total_entries: 3 },
+    isLoading: false,
+  })),
+}));
+
+vi.mock("src/hooks/useSelectedVersion", () => ({
+  default: vi.fn(() => undefined),
+}));
+
+const { useDagRunServiceGetDagRun } = await import("openapi/queries");
+
+const mockRunData = {
+  bundle_version: null,
+  conf: null,
+  dag_display_name: "test_dag",
+  dag_id: "test_dag",
+  dag_versions: [dagVersionV1, dagVersionV2],
+  end_date: null,
+  has_missed_deadline: false,
+  logical_date: null,
+  note: null,
+  partition_key: null,
+  queued_at: null,
+  run_after: "2025-01-01T00:00:00Z",
+  run_id: "run_1",
+  run_type: "manual" as const,
+  start_date: null,
+  state: "success" as const,
+  triggered_by: "ui" as const,
+  triggering_user_name: null,
+};
+
+const getItems = (container: HTMLElement) => 
container.querySelectorAll(".chakra-select__item");
+
+describe("DagVersionSelect", () => {
+  it("shows all versions when no DagRun is selected", () => {
+    mockParams = { dagId: "test_dag" };
+    const { container } = render(<DagVersionSelect />, { wrapper: Wrapper });
+
+    expect(getItems(container)).toHaveLength(3);
+  });
+
+  it("shows only the selected run's versions when a DagRun is selected", () => 
{
+    mockParams = { dagId: "test_dag", runId: "run_1" };
+    vi.mocked(useDagRunServiceGetDagRun).mockReturnValue({
+      data: mockRunData,
+      isLoading: false,
+    } as ReturnType<typeof useDagRunServiceGetDagRun>);
+
+    const { container } = render(<DagVersionSelect />, { wrapper: Wrapper });
+
+    expect(getItems(container)).toHaveLength(2);
+  });
+});
diff --git a/airflow-core/src/airflow/ui/src/components/DagVersionSelect.tsx 
b/airflow-core/src/airflow/ui/src/components/DagVersionSelect.tsx
index 95d9b8870fd..5ec0f97eb48 100644
--- a/airflow-core/src/airflow/ui/src/components/DagVersionSelect.tsx
+++ b/airflow-core/src/airflow/ui/src/components/DagVersionSelect.tsx
@@ -20,7 +20,7 @@ import { createListCollection, Flex, Select, type 
SelectValueChangeDetails, Text
 import { useTranslation } from "react-i18next";
 import { useParams, useSearchParams } from "react-router-dom";
 
-import { useDagVersionServiceGetDagVersions } from "openapi/queries";
+import { useDagRunServiceGetDagRun, useDagVersionServiceGetDagVersions } from 
"openapi/queries";
 import type { DagVersionResponse } from "openapi/requests/types.gen";
 import { SearchParamsKeys } from "src/constants/searchParams";
 import useSelectedVersion from "src/hooks/useSelectedVersion";
@@ -34,14 +34,27 @@ type VersionSelected = {
 
 export const DagVersionSelect = ({ showLabel = true }: { readonly showLabel?: 
boolean }) => {
   const { t: translate } = useTranslation("components");
-  const { dagId = "" } = useParams();
+  const { dagId = "", runId } = useParams();
   const { data, isLoading } = useDagVersionServiceGetDagVersions({ dagId, 
orderBy: ["-version_number"] });
+  const { data: runData } = useDagRunServiceGetDagRun({ dagId, dagRunId: runId 
?? "" }, undefined, {
+    enabled: Boolean(runId),
+  });
   const [searchParams, setSearchParams] = useSearchParams();
   const selectedVersionNumber = useSelectedVersion();
-  const selectedVersion = data?.dag_versions.find((dv) => dv.version_number 
=== selectedVersionNumber);
+
+  // When a DagRun is selected, show only that run's versions. Otherwise, show 
all versions.
+  const allVersions = data?.dag_versions ?? [];
+  const versions: Array<DagVersionResponse> =
+    runId !== undefined && runData
+      ? [...runData.dag_versions].sort(
+          (versionA, versionB) => versionB.version_number - 
versionA.version_number,
+        )
+      : allVersions;
+
+  const selectedVersion = versions.find((dv) => dv.version_number === 
selectedVersionNumber);
 
   const versionOptions = createListCollection({
-    items: (data?.dag_versions ?? []).map((dv) => ({ value: dv.version_number, 
version: dv })),
+    items: versions.map((dv) => ({ value: dv.version_number, version: dv })),
   });
 
   const handleStateChange = ({ items }: 
SelectValueChangeDetails<VersionSelected>) => {
@@ -55,7 +68,7 @@ export const DagVersionSelect = ({ showLabel = true }: { 
readonly showLabel?: bo
     <Select.Root
       collection={versionOptions}
       data-testid="dag-run-select"
-      disabled={isLoading || !data?.dag_versions}
+      disabled={isLoading || versions.length === 0}
       onValueChange={handleStateChange}
       size="sm"
       value={selectedVersionNumber === undefined ? [] : 
[selectedVersionNumber.toString()]}

Reply via email to