You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by "KatalKavya96 (via GitHub)" <gi...@apache.org> on 2025/09/17 23:01:03 UTC
[PR] UI : Implementing Filterbar in Dag -> Tasks [airflow]
KatalKavya96 opened a new pull request, #55811:
URL: https://github.com/apache/airflow/pull/55811
### UI: Add FilterBar to DAG → Tasks page (with URL-synced filters + tests)
### What
Introduce the FilterBar on the DAG Tasks page so users can quickly refine the task list. This PR also adds a lightweight test harness for the Select-based filters and stabilizes unit tests.
### Why
Filtering tasks by operator, name, or mapping status is a common workflow when DAGs have many tasks. Surfacing a consistent FilterBar here improves discoverability and aligns this page with other areas of the UI. Persisting filters in the URL enables shareable links and reliable back/forward navigation.
### Key changes
- Add TaskFilters to /dags/:dagId/tasks:
- Search tasks (name_pattern) — free-text.
- Operators (operator) — multi-select from task payload (e.g., BashOperator, PythonOperator).
- Mapped (mapped) — single-select (true/false).
- Query-string sync via useSearchParams:
- Selecting/changing filters writes name_pattern=…, operator=…, mapped=….
- Resets page=1 when filters change.
### Tests:
- TaskFilters.spec.tsx validates options are built from payload and that URL params update as expected.
- SelectFilter.spec.tsx exercises single/multi-select behaviour.
- Provide a minimal mock for src/components/ui Menu + Select to avoid portal/DOM flakiness in Vitest and to assert against a native <select> (stable and accessible in JSDOM).
No backend/API changes; UI-only.
Backwards compatibility
No breaking changes; filters are additive and default to no filtering.
Screenshots / demo
N/A (behavior is covered by tests; happy to add screenshots if reviewers would like).
Solves #55520
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] UI : Implementing Filterbar in Dag -> Tasks [airflow]
Posted by "KatalKavya96 (via GitHub)" <gi...@apache.org>.
KatalKavya96 commented on PR #55811:
URL: https://github.com/apache/airflow/pull/55811#issuecomment-3312328271
@pierrejeambrun Yes the spec files are the tests i was writing for the changed UI. If we do not require those tests now i can drop them and make other changes requested by you. Please let me know. Thanks!
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] UI : Implementing Filterbar in Dag -> Tasks [airflow]
Posted by "guan404ming (via GitHub)" <gi...@apache.org>.
guan404ming commented on PR #55811:
URL: https://github.com/apache/airflow/pull/55811#issuecomment-3859886467
Thanks!
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] UI : Implementing Filterbar in Dag -> Tasks [airflow]
Posted by "BrianLii (via GitHub)" <gi...@apache.org>.
BrianLii commented on PR #55811:
URL: https://github.com/apache/airflow/pull/55811#issuecomment-3918595536
Thanks for the PR! Could you please resolve the conflict again?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] UI : Implementing Filterbar in Dag -> Tasks [airflow]
Posted by "pierrejeambrun (via GitHub)" <gi...@apache.org>.
pierrejeambrun commented on code in PR #55811:
URL: https://github.com/apache/airflow/pull/55811#discussion_r2362863520
##########
airflow-core/src/airflow/ui/src/pages/Dag/Tasks/TaskFilters/TaskFilters.tsx:
##########
@@ -78,59 +53,116 @@ export const TaskFilters = ({ tasksData }: { readonly tasksData: TaskCollectionR
{ key: "true", label: translate("mapped") },
{ key: "false", label: translate("notMapped") },
];
- const taskNamePattern = searchParams.get(NAME_PATTERN) ?? "";
- const handleSearchChange = (value: string) => {
- if (value) {
- searchParams.set(NAME_PATTERN, value);
- } else {
- searchParams.delete(NAME_PATTERN);
+
+ // Convert to FilterBar select option shape (label/value)
+ const operatorOptions = allOperatorNames
+ .map((value) => ({ label: value, value }))
+ .sort((left, right) => left.label.localeCompare(right.label));
+ const triggerRuleOptions = allTriggerRules
+ .map((value) => ({ label: value, value }))
+ .sort((left, right) => left.label.localeCompare(right.label));
+ const retryValueOptions = allRetryValues
+ .map((value) => ({ label: value, value }))
+ .sort((left, right) => left.label.localeCompare(right.label));
+ const mappedOptions = allMappedValues.map(({ key, label }) => ({ label, value: key }));
+
+ // FilterBar configs (keys unchanged; labels stick to prior wording)
+ const configsUnfiltered: Array<FilterConfig | false> = [
+ {
+ hotkeyDisabled: true,
+ key: NAME_PATTERN,
+ label: translate("searchTasks"),
+ placeholder: translate("searchTasks"),
+ type: "text",
+ },
+ operatorOptions.length > 0 && {
+ key: OPERATOR,
+ label: translate("selectOperator", { defaultValue: "Operators" }),
+ multiple: true,
+ options: operatorOptions,
+ type: "select",
+ },
+ triggerRuleOptions.length > 0 && {
+ key: TRIGGER_RULE,
+ label: translate("selectTriggerRules", { defaultValue: "Trigger rules" }),
+ multiple: true,
+ options: triggerRuleOptions,
+ type: "select",
+ },
+ retryValueOptions.length > 0 && {
+ key: RETRIES,
+ label: translate("retries", { defaultValue: "Retry values" }),
+ multiple: true,
+ options: retryValueOptions,
+ type: "select",
+ },
+ {
+ key: MAPPED,
+ label: translate("mapped", { defaultValue: "Mapped" }),
+ multiple: false,
+ options: mappedOptions,
+ type: "select",
+ },
+ ];
Review Comment:
Task Instances list are also displayed on TI details view and DagRun details view. There some filters should be removed accordingly e.g On a TI (group or mapped index), dag run and dag id are fixed, those filters shouldn't be possible. Similarly on a specific dag run in the grid, listing TI, we shouldn't be able to filter per dag run, because it is already set.
You can take a look at the HITL `FilterBar` implementation to take an example from.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] UI : Implementing Filterbar in Dag -> Tasks [airflow]
Posted by "pierrejeambrun (via GitHub)" <gi...@apache.org>.
pierrejeambrun commented on code in PR #55811:
URL: https://github.com/apache/airflow/pull/55811#discussion_r2394868061
##########
airflow-core/src/airflow/ui/src/pages/Dag/Tasks/TaskFilters/TaskFilters.tsx:
##########
@@ -78,59 +53,129 @@ export const TaskFilters = ({ tasksData }: { readonly tasksData: TaskCollectionR
{ key: "true", label: translate("mapped") },
{ key: "false", label: translate("notMapped") },
];
- const taskNamePattern = searchParams.get(NAME_PATTERN) ?? "";
- const handleSearchChange = (value: string) => {
- if (value) {
- searchParams.set(NAME_PATTERN, value);
- } else {
- searchParams.delete(NAME_PATTERN);
+
+ // Convert to FilterBar select option shape (label/value)
+ const operatorOptions = allOperatorNames
+ .map((value) => ({ label: value, value }))
+ .sort((left, right) => left.label.localeCompare(right.label));
+ const triggerRuleOptions = allTriggerRules
+ .map((value) => ({ label: value, value }))
+ .sort((left, right) => left.label.localeCompare(right.label));
+ const retryValueOptions = allRetryValues
+ .map((value) => ({ label: value, value }))
+ .sort((left, right) => left.label.localeCompare(right.label));
+ const mappedOptions = allMappedValues.map(({ key, label }) => ({ label, value: key }));
+
+ // Narrow falsy entries without hard casts
+ const isFilterConfig = (x: FilterConfig | false): x is FilterConfig => x !== false;
+
+ // FilterBar configs (keys unchanged; labels stick to prior wording)
+ const configsUnfiltered: Array<FilterConfig | false> = [
+ {
+ hotkeyDisabled: true,
+ key: NAME_PATTERN,
+ label: translate("searchTasks"),
+ placeholder: translate("searchTasks"),
+ type: "text",
+ },
+ operatorOptions.length > 0 && {
+ key: OPERATOR,
+ label: translate("selectOperator", { defaultValue: "Operators" }),
+ multiple: true,
+ options: operatorOptions,
+ type: "select",
+ },
+ triggerRuleOptions.length > 0 && {
+ key: TRIGGER_RULE,
+ label: translate("selectTriggerRules", { defaultValue: "Trigger rules" }),
+ multiple: true,
+ options: triggerRuleOptions,
+ type: "select",
+ },
+ retryValueOptions.length > 0 && {
Review Comment:
This filter config should directly come from the hook. You don't have to create the full config manually, so those can be re-used by other filter bars.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] UI : Implementing Filterbar in Dag -> Tasks [airflow]
Posted by "RoyLee1224 (via GitHub)" <gi...@apache.org>.
RoyLee1224 commented on PR #55811:
URL: https://github.com/apache/airflow/pull/55811#issuecomment-3304834677
A lot of these changes seem to be variable renames and style adjustments. Could you please double-check that only necessary changes are included in this PR? It will make the review process much easier.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] UI : Implementing Filterbar in Dag -> Tasks [airflow]
Posted by "KatalKavya96 (via GitHub)" <gi...@apache.org>.
KatalKavya96 commented on PR #55811:
URL: https://github.com/apache/airflow/pull/55811#issuecomment-3318017508
@pierrejeambrun I have made a few changes suggested by you.Please review this PR once again. Thanks
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] UI : Implementing Filterbar in Dag -> Tasks [airflow]
Posted by "KatalKavya96 (via GitHub)" <gi...@apache.org>.
KatalKavya96 commented on PR #55811:
URL: https://github.com/apache/airflow/pull/55811#issuecomment-3918603004
@BrianLii Yes working on it, will push the latest code in 1-2 days
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] UI : Implementing Filterbar in Dag -> Tasks [airflow]
Posted by "pierrejeambrun (via GitHub)" <gi...@apache.org>.
pierrejeambrun commented on code in PR #55811:
URL: https://github.com/apache/airflow/pull/55811#discussion_r2394831710
##########
airflow-core/src/airflow/ui/src/pages/Dag/Tasks/TaskFilters/TaskFilters.tsx:
##########
@@ -78,59 +53,129 @@ export const TaskFilters = ({ tasksData }: { readonly tasksData: TaskCollectionR
{ key: "true", label: translate("mapped") },
{ key: "false", label: translate("notMapped") },
];
- const taskNamePattern = searchParams.get(NAME_PATTERN) ?? "";
- const handleSearchChange = (value: string) => {
- if (value) {
- searchParams.set(NAME_PATTERN, value);
- } else {
- searchParams.delete(NAME_PATTERN);
+
+ // Convert to FilterBar select option shape (label/value)
+ const operatorOptions = allOperatorNames
+ .map((value) => ({ label: value, value }))
+ .sort((left, right) => left.label.localeCompare(right.label));
+ const triggerRuleOptions = allTriggerRules
+ .map((value) => ({ label: value, value }))
+ .sort((left, right) => left.label.localeCompare(right.label));
+ const retryValueOptions = allRetryValues
+ .map((value) => ({ label: value, value }))
+ .sort((left, right) => left.label.localeCompare(right.label));
+ const mappedOptions = allMappedValues.map(({ key, label }) => ({ label, value: key }));
+
+ // Narrow falsy entries without hard casts
+ const isFilterConfig = (x: FilterConfig | false): x is FilterConfig => x !== false;
+
+ // FilterBar configs (keys unchanged; labels stick to prior wording)
+ const configsUnfiltered: Array<FilterConfig | false> = [
+ {
+ hotkeyDisabled: true,
+ key: NAME_PATTERN,
+ label: translate("searchTasks"),
+ placeholder: translate("searchTasks"),
+ type: "text",
+ },
+ operatorOptions.length > 0 && {
+ key: OPERATOR,
+ label: translate("selectOperator", { defaultValue: "Operators" }),
+ multiple: true,
+ options: operatorOptions,
+ type: "select",
+ },
+ triggerRuleOptions.length > 0 && {
+ key: TRIGGER_RULE,
+ label: translate("selectTriggerRules", { defaultValue: "Trigger rules" }),
+ multiple: true,
+ options: triggerRuleOptions,
+ type: "select",
+ },
+ retryValueOptions.length > 0 && {
+ key: RETRIES,
+ label: translate("retries", { defaultValue: "Retry values" }),
+ multiple: true,
+ options: retryValueOptions,
+ type: "select",
+ },
+ {
+ key: MAPPED,
+ label: translate("mapped", { defaultValue: "Mapped" }),
+ multiple: false,
+ options: mappedOptions,
+ type: "select",
+ },
+ ];
+
+ // Make this a mutable array type to satisfy FilterBar's prop
+ const configs: Array<FilterConfig> = configsUnfiltered.filter(isFilterConfig);
+
+ // Initial values mirror previous local names
+ const initialValues = {
+ [MAPPED]: selectedMapped,
+ [NAME_PATTERN]: taskNamePattern || undefined,
+ [OPERATOR]: selectedOperators.length ? selectedOperators : undefined,
+ [RETRIES]: selectedRetries.length ? selectedRetries : undefined,
+ [TRIGGER_RULE]: selectedTriggerRules.length ? selectedTriggerRules : undefined,
+ };
+
+ // Single place to write the URL params (replaces the old individual handlers)
+ const onFiltersChange = (record: Record<string, unknown>): void => {
+ const next = new URLSearchParams(searchParams);
+
+ // clear the filter-related keys before writing
+ [NAME_PATTERN, OPERATOR, TRIGGER_RULE, RETRIES, MAPPED, "page"].forEach((key) => next.delete(key));
Review Comment:
It seems that filters are not persisted to the URL query params.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] UI : Implementing Filterbar in Dag -> Tasks [airflow]
Posted by "KatalKavya96 (via GitHub)" <gi...@apache.org>.
KatalKavya96 commented on PR #55811:
URL: https://github.com/apache/airflow/pull/55811#issuecomment-3829127806
@guan404ming Sure working on the conflicts, will push code soon!
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] UI : Implementing Filterbar in Dag -> Tasks [airflow]
Posted by "potiuk (via GitHub)" <gi...@apache.org>.
potiuk commented on PR #55811:
URL: https://github.com/apache/airflow/pull/55811#issuecomment-4194979790
This draft pull request has had no activity from the author for over 3 weeks.
**@KatalKavya96**, you are welcome to reopen this PR when you are ready to continue working on it. Thank you for your contribution!
<!-- Pull Request quality criteria -->
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] UI : Implementing Filterbar in Dag -> Tasks [airflow]
Posted by "pierrejeambrun (via GitHub)" <gi...@apache.org>.
pierrejeambrun commented on code in PR #55811:
URL: https://github.com/apache/airflow/pull/55811#discussion_r2394831710
##########
airflow-core/src/airflow/ui/src/pages/Dag/Tasks/TaskFilters/TaskFilters.tsx:
##########
@@ -78,59 +53,129 @@ export const TaskFilters = ({ tasksData }: { readonly tasksData: TaskCollectionR
{ key: "true", label: translate("mapped") },
{ key: "false", label: translate("notMapped") },
];
- const taskNamePattern = searchParams.get(NAME_PATTERN) ?? "";
- const handleSearchChange = (value: string) => {
- if (value) {
- searchParams.set(NAME_PATTERN, value);
- } else {
- searchParams.delete(NAME_PATTERN);
+
+ // Convert to FilterBar select option shape (label/value)
+ const operatorOptions = allOperatorNames
+ .map((value) => ({ label: value, value }))
+ .sort((left, right) => left.label.localeCompare(right.label));
+ const triggerRuleOptions = allTriggerRules
+ .map((value) => ({ label: value, value }))
+ .sort((left, right) => left.label.localeCompare(right.label));
+ const retryValueOptions = allRetryValues
+ .map((value) => ({ label: value, value }))
+ .sort((left, right) => left.label.localeCompare(right.label));
+ const mappedOptions = allMappedValues.map(({ key, label }) => ({ label, value: key }));
+
+ // Narrow falsy entries without hard casts
+ const isFilterConfig = (x: FilterConfig | false): x is FilterConfig => x !== false;
+
+ // FilterBar configs (keys unchanged; labels stick to prior wording)
+ const configsUnfiltered: Array<FilterConfig | false> = [
+ {
+ hotkeyDisabled: true,
+ key: NAME_PATTERN,
+ label: translate("searchTasks"),
+ placeholder: translate("searchTasks"),
+ type: "text",
+ },
+ operatorOptions.length > 0 && {
+ key: OPERATOR,
+ label: translate("selectOperator", { defaultValue: "Operators" }),
+ multiple: true,
+ options: operatorOptions,
+ type: "select",
+ },
+ triggerRuleOptions.length > 0 && {
+ key: TRIGGER_RULE,
+ label: translate("selectTriggerRules", { defaultValue: "Trigger rules" }),
+ multiple: true,
+ options: triggerRuleOptions,
+ type: "select",
+ },
+ retryValueOptions.length > 0 && {
+ key: RETRIES,
+ label: translate("retries", { defaultValue: "Retry values" }),
+ multiple: true,
+ options: retryValueOptions,
+ type: "select",
+ },
+ {
+ key: MAPPED,
+ label: translate("mapped", { defaultValue: "Mapped" }),
+ multiple: false,
+ options: mappedOptions,
+ type: "select",
+ },
+ ];
+
+ // Make this a mutable array type to satisfy FilterBar's prop
+ const configs: Array<FilterConfig> = configsUnfiltered.filter(isFilterConfig);
+
+ // Initial values mirror previous local names
+ const initialValues = {
+ [MAPPED]: selectedMapped,
+ [NAME_PATTERN]: taskNamePattern || undefined,
+ [OPERATOR]: selectedOperators.length ? selectedOperators : undefined,
+ [RETRIES]: selectedRetries.length ? selectedRetries : undefined,
+ [TRIGGER_RULE]: selectedTriggerRules.length ? selectedTriggerRules : undefined,
+ };
+
+ // Single place to write the URL params (replaces the old individual handlers)
+ const onFiltersChange = (record: Record<string, unknown>): void => {
+ const next = new URLSearchParams(searchParams);
+
+ // clear the filter-related keys before writing
+ [NAME_PATTERN, OPERATOR, TRIGGER_RULE, RETRIES, MAPPED, "page"].forEach((key) => next.delete(key));
Review Comment:
Filters are not persisted to the URL query params.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] UI : Implementing Filterbar in Dag -> Tasks [airflow]
Posted by "KatalKavya96 (via GitHub)" <gi...@apache.org>.
KatalKavya96 commented on PR #55811:
URL: https://github.com/apache/airflow/pull/55811#issuecomment-3721745564
@bbovenzi On it again!, Let me get back to you with current status of this PR within 24 hours.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] UI : Implementing Filterbar in Dag -> Tasks [airflow]
Posted by "potiuk (via GitHub)" <gi...@apache.org>.
potiuk closed pull request #55811: UI : Implementing Filterbar in Dag -> Tasks
URL: https://github.com/apache/airflow/pull/55811
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] UI : Implementing Filterbar in Dag -> Tasks [airflow]
Posted by "guan404ming (via GitHub)" <gi...@apache.org>.
guan404ming commented on PR #55811:
URL: https://github.com/apache/airflow/pull/55811#issuecomment-3823172098
Thanks for the update. Could you please help resolve the conflict? Thanks!
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] UI : Implementing Filterbar in Dag -> Tasks [airflow]
Posted by "pierrejeambrun (via GitHub)" <gi...@apache.org>.
pierrejeambrun commented on code in PR #55811:
URL: https://github.com/apache/airflow/pull/55811#discussion_r2394868061
##########
airflow-core/src/airflow/ui/src/pages/Dag/Tasks/TaskFilters/TaskFilters.tsx:
##########
@@ -78,59 +53,129 @@ export const TaskFilters = ({ tasksData }: { readonly tasksData: TaskCollectionR
{ key: "true", label: translate("mapped") },
{ key: "false", label: translate("notMapped") },
];
- const taskNamePattern = searchParams.get(NAME_PATTERN) ?? "";
- const handleSearchChange = (value: string) => {
- if (value) {
- searchParams.set(NAME_PATTERN, value);
- } else {
- searchParams.delete(NAME_PATTERN);
+
+ // Convert to FilterBar select option shape (label/value)
+ const operatorOptions = allOperatorNames
+ .map((value) => ({ label: value, value }))
+ .sort((left, right) => left.label.localeCompare(right.label));
+ const triggerRuleOptions = allTriggerRules
+ .map((value) => ({ label: value, value }))
+ .sort((left, right) => left.label.localeCompare(right.label));
+ const retryValueOptions = allRetryValues
+ .map((value) => ({ label: value, value }))
+ .sort((left, right) => left.label.localeCompare(right.label));
+ const mappedOptions = allMappedValues.map(({ key, label }) => ({ label, value: key }));
+
+ // Narrow falsy entries without hard casts
+ const isFilterConfig = (x: FilterConfig | false): x is FilterConfig => x !== false;
+
+ // FilterBar configs (keys unchanged; labels stick to prior wording)
+ const configsUnfiltered: Array<FilterConfig | false> = [
+ {
+ hotkeyDisabled: true,
+ key: NAME_PATTERN,
+ label: translate("searchTasks"),
+ placeholder: translate("searchTasks"),
+ type: "text",
+ },
+ operatorOptions.length > 0 && {
+ key: OPERATOR,
+ label: translate("selectOperator", { defaultValue: "Operators" }),
+ multiple: true,
+ options: operatorOptions,
+ type: "select",
+ },
+ triggerRuleOptions.length > 0 && {
+ key: TRIGGER_RULE,
+ label: translate("selectTriggerRules", { defaultValue: "Trigger rules" }),
+ multiple: true,
+ options: triggerRuleOptions,
+ type: "select",
+ },
+ retryValueOptions.length > 0 && {
Review Comment:
This filter config should directly come from the hook. You don't have to create the full config manually, so those can be re-used by other filter bars.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] UI : Implementing Filterbar in Dag -> Tasks [airflow]
Posted by "pierrejeambrun (via GitHub)" <gi...@apache.org>.
pierrejeambrun commented on PR #55811:
URL: https://github.com/apache/airflow/pull/55811#issuecomment-3396951869
Hey @KatalKavya96, let me know if you need help addressing the comments.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] UI : Implementing Filterbar in Dag -> Tasks [airflow]
Posted by "KatalKavya96 (via GitHub)" <gi...@apache.org>.
KatalKavya96 commented on PR #55811:
URL: https://github.com/apache/airflow/pull/55811#issuecomment-3329766219
@pierrejeambrun Thanks for the reviews,
I have applied the new FilterBar only on the Tasks page in this PR. For TI/DagRun detail views (where some params are fixed), I can either:
- keep this PR focused on Tasks and handle TI/DagRun in a follow-up (hiding context-fixed filters, similar to HITL), or
- extend this PR to cover TI/DagRun as well.
What is your preference?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] UI : Implementing Filterbar in Dag -> Tasks [airflow]
Posted by "jscheffl (via GitHub)" <gi...@apache.org>.
jscheffl commented on PR #55811:
URL: https://github.com/apache/airflow/pull/55811#issuecomment-4063978237
@KatalKavya96 This PR has been converted to **draft** because it does not yet meet our [Pull Request quality criteria](https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#pull-request-quality-criteria).
**Issues found:**
- :x: **Merge conflicts**: This PR has merge conflicts with the `main` branch. Your branch is 3735 commits behind `main`. Please rebase your branch (`git fetch origin && git rebase origin/main`), resolve the conflicts, and push again. See [contributing quick start](https://github.com/apache/airflow/blob/main/contributing-docs/03a_contributors_quick_start_beginners.rst).
> **Note:** Your branch is **3735 commits behind `main`**. Some check failures may be caused by changes in the base branch rather than by your PR. Please rebase your branch and push again to get up-to-date CI results.
**What to do next:**
- The comment informs you what you need to do.
- Fix each issue, then mark the PR as "Ready for review" in the GitHub UI - but only after making sure that all the issues are fixed.
- Maintainers will then proceed with a normal review.
Converting a PR to draft is **not** a rejection — it is an invitation to bring the PR up to the project's standards so that maintainer review time is spent productively. If you have questions, feel free to ask on the [Airflow Slack](https://s.apache.org/airflow-slack).
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] UI : Implementing Filterbar in Dag -> Tasks [airflow]
Posted by "KatalKavya96 (via GitHub)" <gi...@apache.org>.
KatalKavya96 commented on PR #55811:
URL: https://github.com/apache/airflow/pull/55811#issuecomment-3305745510
@RoyLee1224 I have removed all the things which could have been unnecessary. Please suggest further steps according to requirements
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] UI : Implementing Filterbar in Dag -> Tasks [airflow]
Posted by "pierrejeambrun (via GitHub)" <gi...@apache.org>.
pierrejeambrun commented on code in PR #55811:
URL: https://github.com/apache/airflow/pull/55811#discussion_r2362843852
##########
airflow-core/src/airflow/ui/src/pages/Dag/Tasks/TaskFilters/TaskFilters.tsx:
##########
@@ -78,59 +53,116 @@ export const TaskFilters = ({ tasksData }: { readonly tasksData: TaskCollectionR
{ key: "true", label: translate("mapped") },
{ key: "false", label: translate("notMapped") },
];
- const taskNamePattern = searchParams.get(NAME_PATTERN) ?? "";
- const handleSearchChange = (value: string) => {
- if (value) {
- searchParams.set(NAME_PATTERN, value);
- } else {
- searchParams.delete(NAME_PATTERN);
+
+ // Convert to FilterBar select option shape (label/value)
+ const operatorOptions = allOperatorNames
+ .map((value) => ({ label: value, value }))
+ .sort((left, right) => left.label.localeCompare(right.label));
+ const triggerRuleOptions = allTriggerRules
+ .map((value) => ({ label: value, value }))
+ .sort((left, right) => left.label.localeCompare(right.label));
+ const retryValueOptions = allRetryValues
+ .map((value) => ({ label: value, value }))
+ .sort((left, right) => left.label.localeCompare(right.label));
+ const mappedOptions = allMappedValues.map(({ key, label }) => ({ label, value: key }));
+
+ // FilterBar configs (keys unchanged; labels stick to prior wording)
+ const configsUnfiltered: Array<FilterConfig | false> = [
+ {
+ hotkeyDisabled: true,
+ key: NAME_PATTERN,
+ label: translate("searchTasks"),
+ placeholder: translate("searchTasks"),
+ type: "text",
+ },
+ operatorOptions.length > 0 && {
+ key: OPERATOR,
+ label: translate("selectOperator", { defaultValue: "Operators" }),
+ multiple: true,
+ options: operatorOptions,
+ type: "select",
+ },
+ triggerRuleOptions.length > 0 && {
+ key: TRIGGER_RULE,
+ label: translate("selectTriggerRules", { defaultValue: "Trigger rules" }),
+ multiple: true,
+ options: triggerRuleOptions,
+ type: "select",
+ },
+ retryValueOptions.length > 0 && {
+ key: RETRIES,
+ label: translate("retries", { defaultValue: "Retry values" }),
+ multiple: true,
+ options: retryValueOptions,
+ type: "select",
+ },
+ {
+ key: MAPPED,
+ label: translate("mapped", { defaultValue: "Mapped" }),
+ multiple: false,
+ options: mappedOptions,
+ type: "select",
+ },
+ ];
+
+ const configs: Array<FilterConfig> = configsUnfiltered.filter(Boolean) as Array<FilterConfig>;
+
+ // Initial values mirror previous local names
+ const initialValues = {
+ [MAPPED]: selectedMapped,
+ [NAME_PATTERN]: taskNamePattern || undefined,
+ [OPERATOR]: selectedOperators.length ? selectedOperators : undefined,
+ [RETRIES]: selectedRetries.length ? selectedRetries : undefined,
+ [TRIGGER_RULE]: selectedTriggerRules.length ? selectedTriggerRules : undefined,
+ };
+
+ // Single place to write the URL params (replaces the old individual handlers)
+ const onFiltersChange = (record: Record<string, unknown>): void => {
+ const next = new URLSearchParams(searchParams);
+
+ // clear the filter-related keys before writing
+ [NAME_PATTERN, OPERATOR, TRIGGER_RULE, RETRIES, MAPPED, "page"].forEach((key) => next.delete(key));
+
+ const name = typeof record[NAME_PATTERN] === "string" ? record[NAME_PATTERN] : "";
+
+ if (name && String(name).trim() !== "") {
+ next.set(NAME_PATTERN, String(name));
+ }
+
+ const operators = Array.isArray(record[OPERATOR]) ? (record[OPERATOR] as Array<string>) : [];
+
+ operators.forEach((val) => next.append(OPERATOR, val));
+
+ const triggers = Array.isArray(record[TRIGGER_RULE]) ? (record[TRIGGER_RULE] as Array<string>) : [];
+
+ triggers.forEach((val) => next.append(TRIGGER_RULE, val));
+
+ const retries = Array.isArray(record[RETRIES]) ? (record[RETRIES] as Array<string>) : [];
+
+ retries.forEach((val) => next.append(RETRIES, val));
+
+ const mapped = typeof record[MAPPED] === "string" ? record[MAPPED] : "";
+
+ if (mapped && String(mapped).trim() !== "") {
+ next.set(MAPPED, String(mapped));
}
- setSearchParams(searchParams);
+
+ // keep the existing behavior used by tests: reset to page 1 on any filter change
+ next.set("page", "1");
+
Review Comment:
Also there is a lot of hard casting happening, we might want to take a look and fix that. (`as`)
##########
airflow-core/src/airflow/ui/src/components/FilterBar/types.ts:
##########
@@ -18,17 +18,24 @@
*/
import type React from "react";
-export type FilterValue = Date | number | string | null | undefined;
+export type FilterValue = Date | number | ReadonlyArray<string> | string | null | undefined;
Review Comment:
Nice, supporting multi values select is cool. We will need that for other entities.
##########
airflow-core/src/airflow/ui/src/pages/Dag/Tasks/TaskFilters/TaskFilters.tsx:
##########
@@ -78,59 +53,116 @@ export const TaskFilters = ({ tasksData }: { readonly tasksData: TaskCollectionR
{ key: "true", label: translate("mapped") },
{ key: "false", label: translate("notMapped") },
];
- const taskNamePattern = searchParams.get(NAME_PATTERN) ?? "";
- const handleSearchChange = (value: string) => {
- if (value) {
- searchParams.set(NAME_PATTERN, value);
- } else {
- searchParams.delete(NAME_PATTERN);
+
+ // Convert to FilterBar select option shape (label/value)
+ const operatorOptions = allOperatorNames
+ .map((value) => ({ label: value, value }))
+ .sort((left, right) => left.label.localeCompare(right.label));
+ const triggerRuleOptions = allTriggerRules
+ .map((value) => ({ label: value, value }))
+ .sort((left, right) => left.label.localeCompare(right.label));
+ const retryValueOptions = allRetryValues
+ .map((value) => ({ label: value, value }))
+ .sort((left, right) => left.label.localeCompare(right.label));
+ const mappedOptions = allMappedValues.map(({ key, label }) => ({ label, value: key }));
+
+ // FilterBar configs (keys unchanged; labels stick to prior wording)
+ const configsUnfiltered: Array<FilterConfig | false> = [
+ {
+ hotkeyDisabled: true,
+ key: NAME_PATTERN,
+ label: translate("searchTasks"),
+ placeholder: translate("searchTasks"),
+ type: "text",
+ },
+ operatorOptions.length > 0 && {
+ key: OPERATOR,
+ label: translate("selectOperator", { defaultValue: "Operators" }),
+ multiple: true,
+ options: operatorOptions,
+ type: "select",
+ },
+ triggerRuleOptions.length > 0 && {
+ key: TRIGGER_RULE,
+ label: translate("selectTriggerRules", { defaultValue: "Trigger rules" }),
+ multiple: true,
+ options: triggerRuleOptions,
+ type: "select",
+ },
+ retryValueOptions.length > 0 && {
+ key: RETRIES,
+ label: translate("retries", { defaultValue: "Retry values" }),
+ multiple: true,
+ options: retryValueOptions,
+ type: "select",
+ },
+ {
+ key: MAPPED,
+ label: translate("mapped", { defaultValue: "Mapped" }),
+ multiple: false,
+ options: mappedOptions,
+ type: "select",
+ },
+ ];
+
+ const configs: Array<FilterConfig> = configsUnfiltered.filter(Boolean) as Array<FilterConfig>;
+
+ // Initial values mirror previous local names
+ const initialValues = {
+ [MAPPED]: selectedMapped,
+ [NAME_PATTERN]: taskNamePattern || undefined,
+ [OPERATOR]: selectedOperators.length ? selectedOperators : undefined,
+ [RETRIES]: selectedRetries.length ? selectedRetries : undefined,
+ [TRIGGER_RULE]: selectedTriggerRules.length ? selectedTriggerRules : undefined,
+ };
+
+ // Single place to write the URL params (replaces the old individual handlers)
+ const onFiltersChange = (record: Record<string, unknown>): void => {
+ const next = new URLSearchParams(searchParams);
+
+ // clear the filter-related keys before writing
+ [NAME_PATTERN, OPERATOR, TRIGGER_RULE, RETRIES, MAPPED, "page"].forEach((key) => next.delete(key));
Review Comment:
Use react hook to get query parameters and path parameters. (useParams, useSearchParams)
##########
airflow-core/src/airflow/ui/src/pages/Dag/Tasks/TaskFilters/TaskFilters.tsx:
##########
@@ -78,59 +53,116 @@ export const TaskFilters = ({ tasksData }: { readonly tasksData: TaskCollectionR
{ key: "true", label: translate("mapped") },
{ key: "false", label: translate("notMapped") },
];
- const taskNamePattern = searchParams.get(NAME_PATTERN) ?? "";
- const handleSearchChange = (value: string) => {
- if (value) {
- searchParams.set(NAME_PATTERN, value);
- } else {
- searchParams.delete(NAME_PATTERN);
+
+ // Convert to FilterBar select option shape (label/value)
+ const operatorOptions = allOperatorNames
+ .map((value) => ({ label: value, value }))
+ .sort((left, right) => left.label.localeCompare(right.label));
+ const triggerRuleOptions = allTriggerRules
+ .map((value) => ({ label: value, value }))
+ .sort((left, right) => left.label.localeCompare(right.label));
+ const retryValueOptions = allRetryValues
+ .map((value) => ({ label: value, value }))
+ .sort((left, right) => left.label.localeCompare(right.label));
+ const mappedOptions = allMappedValues.map(({ key, label }) => ({ label, value: key }));
+
+ // FilterBar configs (keys unchanged; labels stick to prior wording)
+ const configsUnfiltered: Array<FilterConfig | false> = [
+ {
+ hotkeyDisabled: true,
+ key: NAME_PATTERN,
+ label: translate("searchTasks"),
+ placeholder: translate("searchTasks"),
+ type: "text",
+ },
+ operatorOptions.length > 0 && {
+ key: OPERATOR,
+ label: translate("selectOperator", { defaultValue: "Operators" }),
+ multiple: true,
+ options: operatorOptions,
+ type: "select",
+ },
+ triggerRuleOptions.length > 0 && {
+ key: TRIGGER_RULE,
+ label: translate("selectTriggerRules", { defaultValue: "Trigger rules" }),
+ multiple: true,
+ options: triggerRuleOptions,
+ type: "select",
+ },
+ retryValueOptions.length > 0 && {
+ key: RETRIES,
+ label: translate("retries", { defaultValue: "Retry values" }),
+ multiple: true,
+ options: retryValueOptions,
+ type: "select",
+ },
+ {
+ key: MAPPED,
+ label: translate("mapped", { defaultValue: "Mapped" }),
+ multiple: false,
+ options: mappedOptions,
+ type: "select",
+ },
+ ];
+
+ const configs: Array<FilterConfig> = configsUnfiltered.filter(Boolean) as Array<FilterConfig>;
+
+ // Initial values mirror previous local names
+ const initialValues = {
+ [MAPPED]: selectedMapped,
+ [NAME_PATTERN]: taskNamePattern || undefined,
+ [OPERATOR]: selectedOperators.length ? selectedOperators : undefined,
+ [RETRIES]: selectedRetries.length ? selectedRetries : undefined,
+ [TRIGGER_RULE]: selectedTriggerRules.length ? selectedTriggerRules : undefined,
+ };
+
+ // Single place to write the URL params (replaces the old individual handlers)
+ const onFiltersChange = (record: Record<string, unknown>): void => {
+ const next = new URLSearchParams(searchParams);
+
+ // clear the filter-related keys before writing
+ [NAME_PATTERN, OPERATOR, TRIGGER_RULE, RETRIES, MAPPED, "page"].forEach((key) => next.delete(key));
+
+ const name = typeof record[NAME_PATTERN] === "string" ? record[NAME_PATTERN] : "";
+
+ if (name && String(name).trim() !== "") {
+ next.set(NAME_PATTERN, String(name));
+ }
+
+ const operators = Array.isArray(record[OPERATOR]) ? (record[OPERATOR] as Array<string>) : [];
+
+ operators.forEach((val) => next.append(OPERATOR, val));
+
+ const triggers = Array.isArray(record[TRIGGER_RULE]) ? (record[TRIGGER_RULE] as Array<string>) : [];
+
+ triggers.forEach((val) => next.append(TRIGGER_RULE, val));
+
+ const retries = Array.isArray(record[RETRIES]) ? (record[RETRIES] as Array<string>) : [];
+
+ retries.forEach((val) => next.append(RETRIES, val));
+
+ const mapped = typeof record[MAPPED] === "string" ? record[MAPPED] : "";
+
+ if (mapped && String(mapped).trim() !== "") {
+ next.set(MAPPED, String(mapped));
}
- setSearchParams(searchParams);
+
+ // keep the existing behavior used by tests: reset to page 1 on any filter change
+ next.set("page", "1");
+
Review Comment:
Code could be more consistent with other `FilterBar` usage.
##########
airflow-core/src/airflow/ui/src/pages/Dag/Tasks/TaskFilters/TaskFilters.tsx:
##########
@@ -78,59 +53,116 @@ export const TaskFilters = ({ tasksData }: { readonly tasksData: TaskCollectionR
{ key: "true", label: translate("mapped") },
{ key: "false", label: translate("notMapped") },
];
- const taskNamePattern = searchParams.get(NAME_PATTERN) ?? "";
- const handleSearchChange = (value: string) => {
- if (value) {
- searchParams.set(NAME_PATTERN, value);
- } else {
- searchParams.delete(NAME_PATTERN);
+
+ // Convert to FilterBar select option shape (label/value)
+ const operatorOptions = allOperatorNames
+ .map((value) => ({ label: value, value }))
+ .sort((left, right) => left.label.localeCompare(right.label));
+ const triggerRuleOptions = allTriggerRules
+ .map((value) => ({ label: value, value }))
+ .sort((left, right) => left.label.localeCompare(right.label));
+ const retryValueOptions = allRetryValues
+ .map((value) => ({ label: value, value }))
+ .sort((left, right) => left.label.localeCompare(right.label));
+ const mappedOptions = allMappedValues.map(({ key, label }) => ({ label, value: key }));
+
+ // FilterBar configs (keys unchanged; labels stick to prior wording)
+ const configsUnfiltered: Array<FilterConfig | false> = [
+ {
+ hotkeyDisabled: true,
+ key: NAME_PATTERN,
+ label: translate("searchTasks"),
+ placeholder: translate("searchTasks"),
+ type: "text",
+ },
+ operatorOptions.length > 0 && {
+ key: OPERATOR,
+ label: translate("selectOperator", { defaultValue: "Operators" }),
+ multiple: true,
+ options: operatorOptions,
+ type: "select",
+ },
+ triggerRuleOptions.length > 0 && {
+ key: TRIGGER_RULE,
+ label: translate("selectTriggerRules", { defaultValue: "Trigger rules" }),
+ multiple: true,
+ options: triggerRuleOptions,
+ type: "select",
+ },
+ retryValueOptions.length > 0 && {
+ key: RETRIES,
+ label: translate("retries", { defaultValue: "Retry values" }),
+ multiple: true,
+ options: retryValueOptions,
+ type: "select",
+ },
+ {
+ key: MAPPED,
+ label: translate("mapped", { defaultValue: "Mapped" }),
+ multiple: false,
+ options: mappedOptions,
+ type: "select",
+ },
+ ];
Review Comment:
Task Instances list are also displayed on TI details view and DagRun details view. There some filters some be removed accordingly e.g On a TI (group or mapped index), dag run and dag id are fixed, those filters shouldn't be possible.
You can take a look at the HITL `FilterBar` implementation to take an example from.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] UI : Implementing Filterbar in Dag -> Tasks [airflow]
Posted by "bbovenzi (via GitHub)" <gi...@apache.org>.
bbovenzi commented on PR #55811:
URL: https://github.com/apache/airflow/pull/55811#issuecomment-3720368602
@KatalKavya96 pinging again
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] UI : Implementing Filterbar in Dag -> Tasks [airflow]
Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #55811:
URL: https://github.com/apache/airflow/pull/55811#issuecomment-3679786855
This pull request has been automatically marked as stale because it has not had recent activity. It will be closed in 5 days if no further activity occurs. Thank you for your contributions.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@airflow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org