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 ae83f9bf264 UI: Fix "Mark state as..." buttons grayed out when 
task/DAGRun already in target state (#66198) (#66919)
ae83f9bf264 is described below

commit ae83f9bf264618bf66bdf412d58a04c88b8e7d71
Author: Rahul Vats <[email protected]>
AuthorDate: Thu May 14 19:52:40 2026 +0530

    UI: Fix "Mark state as..." buttons grayed out when task/DAGRun already in 
target state (#66198) (#66919)
    
    * UI: Fix "Mark state as..." buttons grayed out when task/DAGRun already in 
target state
    
    Menu items for marking a task instance, task group, or DAG run as
    success/failed were disabled whenever the item's current state matched
    the target state. This blocked users from re-applying the same state
    (e.g. marking an already-succeeded DAG run as success to also flip all
    its tasks). The same bug existed in Airflow 2.x (#36219) and regressed
    in the Airflow 3.x UI redesign.
    
    Remove the state-equality guards from:
    - the `disabled` prop on Menu.Item
    - the `onClick` early-return
    - the hotkey `enabled` conditions
    - the Tooltip `disabled` condition
    
    Add regression tests for MarkRunAsButton to prevent future recurrence.
    
    Fixes #66197
    
    * Replace unit test with inline comments explaining why state-match is not 
disabled
    
    Per review feedback: comments in the source communicate the intent more
    reliably than a separate test file that could be deleted without context.
    
    https://claude.ai/code/session_012oET1NyiNZe44zWbr9GZnn
    
    ---------
    
    
    (cherry picked from commit 505924feaa4de521c364f24d7562a35d951561f0)
    
    Co-authored-by: internetcoffeephone 
<[email protected]>
    Co-authored-by: Claude <[email protected]>
---
 .../ui/src/components/MarkAs/Run/MarkRunAsButton.tsx       | 14 ++++++--------
 .../MarkAs/TaskInstance/MarkTaskInstanceAsButton.tsx       | 14 ++++++--------
 2 files changed, 12 insertions(+), 16 deletions(-)

diff --git 
a/airflow-core/src/airflow/ui/src/components/MarkAs/Run/MarkRunAsButton.tsx 
b/airflow-core/src/airflow/ui/src/components/MarkAs/Run/MarkRunAsButton.tsx
index a71fc8c2821..47025709a5f 100644
--- a/airflow-core/src/airflow/ui/src/components/MarkAs/Run/MarkRunAsButton.tsx
+++ b/airflow-core/src/airflow/ui/src/components/MarkAs/Run/MarkRunAsButton.tsx
@@ -46,7 +46,7 @@ const MarkRunAsButton = ({ dagRun, isHotkeyEnabled = false }: 
Props) => {
       setState("failed");
       onOpen();
     },
-    { enabled: isHotkeyEnabled && dagRun.state !== "failed" },
+    { enabled: isHotkeyEnabled },
   );
 
   useHotkeys(
@@ -55,7 +55,7 @@ const MarkRunAsButton = ({ dagRun, isHotkeyEnabled = false }: 
Props) => {
       setState("success");
       onOpen();
     },
-    { enabled: isHotkeyEnabled && dagRun.state !== "success" },
+    { enabled: isHotkeyEnabled },
   );
 
   return (
@@ -94,20 +94,18 @@ const MarkRunAsButton = ({ dagRun, isHotkeyEnabled = false 
}: Props) => {
               <Tooltip
                 closeDelay={100}
                 content={content}
-                disabled={!isHotkeyEnabled || dagRun.state === menuState}
+                disabled={!isHotkeyEnabled}
                 key={menuState}
                 openDelay={100}
               >
+                {/* Not disabled when state matches: re-applying lets users 
also flip upstream/downstream tasks */}
                 <Menu.Item
                   asChild
                   data-testid={`mark-run-as-${menuState}`}
-                  disabled={dagRun.state === menuState}
                   key={menuState}
                   onClick={() => {
-                    if (dagRun.state !== menuState) {
-                      setState(menuState);
-                      onOpen();
-                    }
+                    setState(menuState);
+                    onOpen();
                   }}
                   value={menuState}
                 >
diff --git 
a/airflow-core/src/airflow/ui/src/components/MarkAs/TaskInstance/MarkTaskInstanceAsButton.tsx
 
b/airflow-core/src/airflow/ui/src/components/MarkAs/TaskInstance/MarkTaskInstanceAsButton.tsx
index 8ae616232b9..19d1e8c75c5 100644
--- 
a/airflow-core/src/airflow/ui/src/components/MarkAs/TaskInstance/MarkTaskInstanceAsButton.tsx
+++ 
b/airflow-core/src/airflow/ui/src/components/MarkAs/TaskInstance/MarkTaskInstanceAsButton.tsx
@@ -47,7 +47,7 @@ const MarkTaskInstanceAsButton = ({ isHotkeyEnabled = false, 
taskInstance }: Pro
       setState("failed");
       onOpen();
     },
-    { enabled: isHotkeyEnabled && taskInstance.state !== "failed" },
+    { enabled: isHotkeyEnabled },
   );
 
   useHotkeys(
@@ -56,7 +56,7 @@ const MarkTaskInstanceAsButton = ({ isHotkeyEnabled = false, 
taskInstance }: Pro
       setState("success");
       onOpen();
     },
-    { enabled: isHotkeyEnabled && taskInstance.state !== "success" },
+    { enabled: isHotkeyEnabled },
   );
 
   return (
@@ -96,19 +96,17 @@ const MarkTaskInstanceAsButton = ({ isHotkeyEnabled = 
false, taskInstance }: Pro
               <Tooltip
                 closeDelay={100}
                 content={content}
-                disabled={!isHotkeyEnabled || taskInstance.state === menuState}
+                disabled={!isHotkeyEnabled}
                 key={menuState}
                 openDelay={100}
               >
+                {/* Not disabled when state matches: re-applying lets users 
also flip upstream/downstream tasks */}
                 <Menu.Item
                   asChild
-                  disabled={taskInstance.state === menuState}
                   key={menuState}
                   onClick={() => {
-                    if (taskInstance.state !== menuState) {
-                      setState(menuState);
-                      onOpen();
-                    }
+                    setState(menuState);
+                    onOpen();
                   }}
                   value={menuState}
                 >

Reply via email to