Skip to content

Commit 505924f

Browse files
UI: Fix "Mark state as..." buttons grayed out when task/DAGRun already in target state (#66198)
* 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 --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 23f1772 commit 505924f

3 files changed

Lines changed: 18 additions & 24 deletions

File tree

airflow-core/src/airflow/ui/src/components/MarkAs/Run/MarkRunAsButton.tsx

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ const MarkRunAsButton = ({ dagRun, isHotkeyEnabled = false }: Props) => {
4646
setState("failed");
4747
onOpen();
4848
},
49-
{ enabled: isHotkeyEnabled && dagRun.state !== "failed" },
49+
{ enabled: isHotkeyEnabled },
5050
);
5151

5252
useHotkeys(
@@ -55,7 +55,7 @@ const MarkRunAsButton = ({ dagRun, isHotkeyEnabled = false }: Props) => {
5555
setState("success");
5656
onOpen();
5757
},
58-
{ enabled: isHotkeyEnabled && dagRun.state !== "success" },
58+
{ enabled: isHotkeyEnabled },
5959
);
6060

6161
return (
@@ -94,20 +94,18 @@ const MarkRunAsButton = ({ dagRun, isHotkeyEnabled = false }: Props) => {
9494
<Tooltip
9595
closeDelay={100}
9696
content={content}
97-
disabled={!isHotkeyEnabled || dagRun.state === menuState}
97+
disabled={!isHotkeyEnabled}
9898
key={menuState}
9999
openDelay={100}
100100
>
101+
{/* Not disabled when state matches: re-applying lets users also flip upstream/downstream tasks */}
101102
<Menu.Item
102103
asChild
103104
data-testid={`mark-run-as-${menuState}`}
104-
disabled={dagRun.state === menuState}
105105
key={menuState}
106106
onClick={() => {
107-
if (dagRun.state !== menuState) {
108-
setState(menuState);
109-
onOpen();
110-
}
107+
setState(menuState);
108+
onOpen();
111109
}}
112110
value={menuState}
113111
>

airflow-core/src/airflow/ui/src/components/MarkAs/TaskGroup/MarkTaskGroupAsButton.tsx

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ const MarkTaskGroupAsButton = ({ groupTaskInstance, isHotkeyEnabled = false }: P
4747
setState("failed");
4848
onOpen();
4949
},
50-
{ enabled: isHotkeyEnabled && groupTaskInstance.state !== "failed" },
50+
{ enabled: isHotkeyEnabled },
5151
);
5252

5353
useHotkeys(
@@ -56,7 +56,7 @@ const MarkTaskGroupAsButton = ({ groupTaskInstance, isHotkeyEnabled = false }: P
5656
setState("success");
5757
onOpen();
5858
},
59-
{ enabled: isHotkeyEnabled && groupTaskInstance.state !== "success" },
59+
{ enabled: isHotkeyEnabled },
6060
);
6161

6262
return (
@@ -96,19 +96,17 @@ const MarkTaskGroupAsButton = ({ groupTaskInstance, isHotkeyEnabled = false }: P
9696
<Tooltip
9797
closeDelay={100}
9898
content={content}
99-
disabled={!isHotkeyEnabled || groupTaskInstance.state === menuState}
99+
disabled={!isHotkeyEnabled}
100100
key={menuState}
101101
openDelay={100}
102102
>
103+
{/* Not disabled when state matches: re-applying lets users also flip upstream/downstream tasks */}
103104
<Menu.Item
104105
asChild
105-
disabled={groupTaskInstance.state === menuState}
106106
key={menuState}
107107
onClick={() => {
108-
if (groupTaskInstance.state !== menuState) {
109-
setState(menuState);
110-
onOpen();
111-
}
108+
setState(menuState);
109+
onOpen();
112110
}}
113111
value={menuState}
114112
>

airflow-core/src/airflow/ui/src/components/MarkAs/TaskInstance/MarkTaskInstanceAsButton.tsx

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ const MarkTaskInstanceAsButton = ({ isHotkeyEnabled = false, taskInstance }: Pro
4747
setState("failed");
4848
onOpen();
4949
},
50-
{ enabled: isHotkeyEnabled && taskInstance.state !== "failed" },
50+
{ enabled: isHotkeyEnabled },
5151
);
5252

5353
useHotkeys(
@@ -56,7 +56,7 @@ const MarkTaskInstanceAsButton = ({ isHotkeyEnabled = false, taskInstance }: Pro
5656
setState("success");
5757
onOpen();
5858
},
59-
{ enabled: isHotkeyEnabled && taskInstance.state !== "success" },
59+
{ enabled: isHotkeyEnabled },
6060
);
6161

6262
return (
@@ -96,19 +96,17 @@ const MarkTaskInstanceAsButton = ({ isHotkeyEnabled = false, taskInstance }: Pro
9696
<Tooltip
9797
closeDelay={100}
9898
content={content}
99-
disabled={!isHotkeyEnabled || taskInstance.state === menuState}
99+
disabled={!isHotkeyEnabled}
100100
key={menuState}
101101
openDelay={100}
102102
>
103+
{/* Not disabled when state matches: re-applying lets users also flip upstream/downstream tasks */}
103104
<Menu.Item
104105
asChild
105-
disabled={taskInstance.state === menuState}
106106
key={menuState}
107107
onClick={() => {
108-
if (taskInstance.state !== menuState) {
109-
setState(menuState);
110-
onOpen();
111-
}
108+
setState(menuState);
109+
onOpen();
112110
}}
113111
value={menuState}
114112
>

0 commit comments

Comments
 (0)