Skip to content

Add Clear All Mapped Tasks button for mapped task instances#60591

Open
VedantMadane wants to merge 8 commits intoapache:mainfrom
VedantMadane:ui-clear-all-mapped-ti
Open

Add Clear All Mapped Tasks button for mapped task instances#60591
VedantMadane wants to merge 8 commits intoapache:mainfrom
VedantMadane:ui-clear-all-mapped-ti

Conversation

@VedantMadane
Copy link

Summary

This PR adds a "Clear All Mapped Tasks" button to the mapped task instance header, allowing users to clear all mapped task instances at once.

Closes #60460

Problem

Currently, there is no way to clear all mapped task instances at once for a specific task. Users have to clear each individual mapped task instance separately, which is tedious when dealing with many mapped instances.

Solution

Added a "Clear All Mapped Tasks" button to the mapped task instance header that clears all map indices for a given task. The backend already supports this functionality - when only the task_id is provided (without map_index), all map indices are targeted for clearing.

Changes

  • ClearAllMappedTaskInstancesButton.tsx: New button component that triggers the dialog
  • ClearAllMappedTaskInstancesDialog.tsx: New dialog component similar to ClearTaskInstanceDialog, but uses task_ids: [taskId] instead of [[taskId, mapIndex]] to clear all mapped instances
  • Header.tsx: Updated to accept dagId and dagRunId props and render the new button
  • MappedTaskInstance.tsx: Updated to pass dagId and dagRunId to the Header component
  • dags.json: Added translation keys for the new feature

Screenshot Location

The button appears in the header of the mapped task instance page (e.g., /dags/{dag_id}/runs/{run_id}/tasks/{task_id}/mapped), next to the task name and statistics.

Testing

  • TypeScript compilation passes
  • The feature uses existing backend functionality that already supports clearing all mapped instances
  • The dialog follows the same patterns as the existing ClearTaskInstanceDialog

@rachanadutta
Copy link
Contributor

rachanadutta commented Jan 15, 2026

Screenshot 2026-01-15 at 11 09 14 PM

Hi @VedantMadane , thanks for the PR — the implementation looks solid 👍

I was actually working on this issue as well (I’m the assignee), and my approach was slightly different on the UI side.

Instead of placing the button in the mapped task header, I was adding the “Clear all mapped task instances” button next to the Filter button in the Task Instances section, to keep it consistent with other bulk actions on that page.

I’ve attached a screenshot below showing the placement I was testing locally.

Functionality-wise, your approach of passing only task_id (without map_index) matches what I had in mind, and we could reuse the same dialog logic.

@maintainers — would you prefer the button in the header (as in this PR), or alongside the filter in the Task Instances section?

Based on your guidance, I’m happy to either:

follow up with a small PR adjusting the placement, or

help refine this PR instead.

Thanks!

@VedantMadane
Copy link
Author

Sorry about that Rachana, feel free to modify this PR or reuse code from it.

@rachanadutta
Copy link
Contributor

rachanadutta commented Jan 16, 2026

Screenshot 2026-01-15 at 10 47 28 PM Hi @VedantMadane — quick check while testing this locally 🙂

On my side, when I open the “Clear All Mapped Task Instances” dialog, the mapped task instances are not appearing in the dialog (the ActionAccordion looks empty).

Could you please share a quick screenshot from your local setup showing whether the mapped task instances are listed correctly in the dialog? That would really help confirm whether this is environment-specific or something we need to adjust in the PR.

Thanks!

@VedantMadane
Copy link
Author

Hi @rachanadutta, thanks for catching this! I found the bug.

The ActionAccordion component requires note and setNote props, but I was only passing affectedTasks. This caused the accordion to render incorrectly and not display the task instances.

I've pushed a fix that adds the missing props. Could you try pulling the latest changes and testing again?

The accordion should now show the list of mapped task instances that will be affected by the clear operation.

@rachanadutta
Copy link
Contributor

@VedantMadane I reviewed and tested the changes locally.
The “Clear all mapped task instances” action is now available in the UI and the mapped task instances are now appearing correctly in the clear dialog, which addresses the original issue. 👍

I tested the clear task instance behavior both locally and on released Airflow (3.1.3) using airflow standalone:

the confirmation dialog shows the affected tasks with No Status,

but the Task Instances list and the individual task instance page still show the previous state (e.g. Success).

This makes it difficult for users to tell from the main page that the clear action actually took effect as there is no success message like delete instance.
That said, this seems like a separate UI refresh / state update issue, and not directly related to the changes in this PR, so I’ll open a follow-up issue to track it separately.

One minor UX thought (happy to defer to maintainers): placing the action closer to the existing +Filter button (instead of the header) might better align with the overall UI patterns, but I understand this is a design choice and should be maintainer-driven.

@pierrejeambrun pierrejeambrun added this to the Airflow 3.2.0 milestone Jan 21, 2026
Copy link
Member

@pierrejeambrun pierrejeambrun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

Tested locally and working as expected.

A few suggestions before we can merge.

Copy link
Contributor

@bbovenzi bbovenzi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We only call mapIndex in a handful of places in our existing ClearTaskInstanceDialog. I wonder if we can add a allMapped boolean param to it to handle this condition instead of making an entire parallel set of components.

…0460)

This adds a 'Clear All Mapped Tasks' button to the mapped task instance
header, allowing users to clear all mapped task instances at once.

Changes:
- Added ClearAllMappedTaskInstancesButton component
- Added ClearAllMappedTaskInstancesDialog component
- Updated MappedTaskInstance Header to include the clear all button
- Added translation keys for the new feature

The backend already supports clearing all map indices when only task_id
is provided (without map_index), so this UI change leverages that
existing functionality.

Closes apache#60460
The ActionAccordion component requires note and setNote props but they were missing, causing the accordion to appear empty.
@VedantMadane VedantMadane force-pushed the ui-clear-all-mapped-ti branch from 50b548d to fba7b51 Compare January 31, 2026 06:18
VedantMadane added a commit to VedantMadane/airflow that referenced this pull request Jan 31, 2026
- Add allMapped boolean prop to ClearTaskInstanceButton and ClearTaskInstanceDialog
- Eliminate need for parallel ClearAllMapped* components
- Fix tooltip ternary to use different translation keys based on allMapped and isHotkeyEnabled
- Conditionally handle mapIndex in 6 places (taskIds, patch hook, confirmation dialog, note patching, title, tooltips)

Addresses review feedback from @bbovenzi in PR apache#60591
VedantMadane added a commit to VedantMadane/airflow that referenced this pull request Jan 31, 2026
- Add allMapped boolean prop to ClearTaskInstanceButton and ClearTaskInstanceDialog
- Eliminate need for parallel ClearAllMapped* components
- Fix tooltip ternary to use different translation keys based on allMapped and isHotkeyEnabled
- Conditionally handle mapIndex in 6 places (taskIds, patch hook, confirmation dialog, note patching, title, tooltips)

Addresses review feedback from @bbovenzi in PR apache#60591
@VedantMadane
Copy link
Author

VedantMadane commented Jan 31, 2026

Added allMapped?: boolean prop to existing components instead of creating parallel ClearAllMapped* components. Commit 5e53ef7

VedantMadane added a commit to VedantMadane/airflow that referenced this pull request Jan 31, 2026
- Delete ClearAllMappedTaskInstancesButton.tsx and ClearAllMappedTaskInstancesDialog.tsx
- Update Header.tsx to use ClearTaskInstanceButton with allMapped=true
- All functionality now consolidated into existing components with allMapped boolean param

Addresses @bbovenzi review feedback in PR apache#60591:
1. Eliminated parallel component set - now using single allMapped param
2. Fixed tooltip ternary to use different translation keys
3. Translation keys already exist in dags.json (clearAllMapped.button, clearAllMapped.buttonTooltip, clearAllMapped.title)
- Keep ClearAllMappedTaskInstancesButton with explicit props (dagId, dagRunId, taskId)
- Delete redundant ClearAllMappedTaskInstancesDialog (200 lines)
- Enhance ClearTaskInstanceDialog to accept both TaskInstanceResponse OR explicit props
- Add allMapped parameter to ClearTaskInstanceDialog for conditional logic
- Fix task_ids API format: [taskId] for all mapped vs [[taskId, mapIndex]] for single
- Fix tooltip ternary to show different text when hotkey disabled
- Handle optional taskInstance fields gracefully (note, dag_version, task_display_name, start_date, logical_date)

Addresses @bbovenzi review feedback in PR apache#60591:
1. Consolidate dialog logic with allMapped param instead of parallel components
2. Fix tooltip ternary dead code (lines 53-55)
3. Properly handle mapIndex in handful of places with conditional logic

Net change: -173 lines of code
@VedantMadane VedantMadane force-pushed the ui-clear-all-mapped-ti branch from ce26f2f to 1db8d12 Compare January 31, 2026 07:17
Copy link
Member

@pierrejeambrun pierrejeambrun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks,

That's looking better.

A few things to address

Comment on lines +61 to +65
// Support both taskInstance and explicit props
const dagId = propDagId ?? taskInstance?.dag_id ?? "";
const dagRunId = propDagRunId ?? taskInstance?.dag_run_id ?? "";
const taskId = propTaskId ?? taskInstance?.task_id ?? "";
const mapIndex = propMapIndex ?? taskInstance?.map_index ?? -1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is confusing and we should probably support only one mode. (TI or explicit props)

dagId,
dagRunId,
mapIndex,
mapIndex: allMapped ? -1 : mapIndex,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's wrong. If "allMapped" we should update the note for all of the mapped instances. And this is done when passing 'None' to the backend, problaby passing null or undefined there.

Comment on lines 260 to 269
if (!allMapped && taskInstance && note !== taskInstance.note) {
mutatePatchTaskInstance({
dagId,
dagRunId,
mapIndex,
requestBody: { note },
taskId,
});
}
onCloseDialog();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to update the note of all mapped task instances. This is just plainly skipping the note I believe when clearing all task instances with a note.

configurable: true,
value: createLocalStorage(),
});

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain why is this code needed? I suppose the test was failing ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:translations area:UI Related to UI/UX. For Frontend Developers. translation:default

Projects

None yet

Development

Successfully merging this pull request may close these issues.

UI - Clear all mapped index for a mapped TI

4 participants