Skip to content

Add date range filter for DAG runs#590

Open
jvanbuel wants to merge 4 commits intomainfrom
claude/add-dagrun-date-filter-V6y40
Open

Add date range filter for DAG runs#590
jvanbuel wants to merge 4 commits intomainfrom
claude/add-dagrun-date-filter-V6y40

Conversation

@jvanbuel
Copy link
Owner

@jvanbuel jvanbuel commented Feb 21, 2026

Summary

This PR adds a date range filter feature for DAG runs, allowing users to filter the DAG run list by start and end dates using an interactive calendar popup.

Key Changes

  • New Date Filter Popup (src/app/model/popup/dagruns/date_filter.rs):

    • Interactive calendar widget for selecting date ranges
    • Supports navigation with vim-style keys (hjkl for days, HJKL for months)
    • Allows independent selection of start and end dates with Tab to toggle between fields
    • Visual highlighting of cursor position, selected dates, and date range
    • Keyboard shortcuts: Space to select, x to clear, Enter to apply, Esc to cancel
  • DAG Run Model Integration (src/app/model/dagruns.rs):

    • Added date_filter field to store the current date range filter
    • Integrated date filter popup into the popup system
    • Added 'd' keybinding to open the date filter popup
    • Displays active date filter in the table title
    • Triggers API refresh when filter is applied
  • API Layer Updates:

    • Modified DagRunOperations trait to accept DagRunDateFilter parameter
    • Updated both V1 and V2 client implementations to pass date filters to API queries
    • V1 uses execution_date_gte/execution_date_lte parameters
    • V2 uses logical_date_gte/logical_date_lte parameters
    • End date is made inclusive by adding one day to the query
  • Worker Message Updates (src/app/worker/mod.rs):

    • Extended UpdateDagRuns message to include date_filter field
    • Updated worker handler to pass filter to API calls
  • UI/UX Enhancements:

    • Added date filter command to help menu
    • Date filter status displayed in DAG run table header when active
    • Comprehensive keyboard help text in the popup

Implementation Details

  • The DagRunDateFilter struct is a simple optional date range container that can be serialized/cloned
  • Calendar rendering uses ratatui's built-in Monthly widget with custom event styling
  • Date range highlighting shows all dates between start and end (inclusive)
  • The popup auto-advances from start date selection to end date selection for better UX
  • Filter state persists across popup open/close cycles until explicitly cleared or changed

https://claude.ai/code/session_017JgxKcniaEptjNFaQ8iPbU

Summary by CodeRabbit

Release Notes

  • New Features

    • Added date range filtering for DAG runs with an interactive calendar-based date picker
    • Press 'd' to open the date filter popup and filter runs by custom start and end dates
    • Widget title now dynamically displays active date filters for quick reference
  • Chores

    • Updated calendar widget dependency

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 21, 2026

Walkthrough

This PR adds optional date range filtering to DAG run listings. It introduces a DagRunDateFilter struct, updates both V1 and V2 Airflow client implementations to accept date filters, adds a calendar-based date filter UI component, and integrates the functionality throughout the application model and worker message handling layers.

Changes

Cohort / File(s) Summary
Dependency & Core Trait Updates
Cargo.toml, src/airflow/traits/dagrun.rs, src/airflow/traits/mod.rs
Added "widget-calendar" feature to ratatui dependency. Introduced new DagRunDateFilter struct with optional start_date and end_date fields. Updated DagRunOperations::list_dagruns trait signature to accept date_filter parameter. Re-exported DagRunDateFilter from traits module.
Airflow Client V1 & V2 Implementations
src/airflow/client/v1/dagrun.rs, src/airflow/client/v2/dagrun.rs
Updated both V1 and V2 client implementations of list_dagruns to accept date_filter parameter. Implemented dynamic query construction using date filter fields: V1 uses execution_date_gte/lte, V2 uses logical_date_gte/lte with day-boundary calculations.
Date Filter UI Component
src/app/model/popup/dagruns/date_filter.rs, src/app/model/popup/dagruns/mod.rs, src/app/model/popup/dagruns/commands.rs
Created new DateFilterPopup component (358 lines) with dual-calendar interface for date range selection. Supports keyboard navigation (arrow keys, h/j/k/l, H/L for months), field toggling (Tab), date selection (Space), and clear (x). Added "Date Filter" command binding to 'd' key in DAGRUN_COMMAND_POP_UP.
DAG Run Model & State Integration
src/app/model/dagruns.rs, src/app/model/dags.rs, src/app/state.rs
Added date_filter field to DagRunModel. Integrated DateFilterPopup into popup handling; pressing 'd' opens date filter. Title now displays date filter summary when active. Updated WorkerMessage::UpdateDagRuns to include date_filter field. Adjusted pattern matching to use wildcard syntax.
Worker Message & Handler Updates
src/app/worker/mod.rs, src/app/worker/dagruns.rs
Extended WorkerMessage::UpdateDagRuns enum variant to carry date_filter: DagRunDateFilter. Updated handle_update_dag_runs signature to accept and propagate date_filter parameter. Adjusted dedup_key handling and message processing to destructure and forward date filter.
API Test Updates
tests/v1_api_test.rs, tests/v2_api_test.rs
Updated test calls to list_dagruns to pass DagRunDateFilter::default() parameter. Added import of DagRunDateFilter from flowrs_tui::airflow::traits.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Model as DagRunModel
    participant Popup as DateFilterPopup
    participant Worker as WorkerThread
    participant Client as AirflowClient
    participant API as Airflow API

    User->>Model: Press 'd'
    Model->>Popup: new(current_date_filter)
    Popup-->>Model: DateFilterPopup created
    
    rect rgba(200, 150, 100, 0.5)
        Note over User,Popup: User navigates & selects dates
        User->>Popup: Arrow/h/j/k/l keys
        Popup->>Popup: Update cursor position
        User->>Popup: Space to select date
        Popup->>Popup: Set start/end date
        User->>Popup: Tab to toggle field
        Popup->>Popup: Switch between Start/End
        User->>Popup: Enter to confirm
    end
    
    Popup-->>Model: Confirmed with date range
    Model->>Model: Update date_filter field
    Model->>Worker: Queue UpdateDagRuns {dag_id, date_filter}
    
    Worker->>Client: list_dagruns(dag_id, date_filter)
    Client->>Client: Build query with date filters
    Client->>API: GET /dags/{dag_id}/dagRuns?logical_date_gte=...&logical_date_lte=...
    API-->>Client: DagRunList
    Client-->>Worker: Return results
    Worker->>Model: Update displayed dag runs
    Model-->>User: Refresh UI with filtered runs
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • PR #424 — Introduced the initial DagRun listing API that this PR extends with date filtering capability
  • PR #563 — Also modifies handle_update_dag_runs signature in src/app/worker/dagruns.rs, overlapping with identifier type changes
  • PR #481 — Updates DAG run listing tests (tests/v1_api_test.rs, tests/v2_api_test.rs) similarly affected by API signature changes
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add date range filter for DAG runs' directly and clearly summarizes the main change across the entire PR, matching the comprehensive feature implementation for date-based filtering.
Docstring Coverage ✅ Passed Docstring coverage is 84.62% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch claude/add-dagrun-date-filter-V6y40

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Add a date range filter to the DAG runs panel using ratatui's calendar
widget. Users can press 'd' to open a calendar popup where they can
select start and end dates to filter which DAG runs are fetched from
the Airflow API.

Key changes:
- Add DagRunDateFilter struct to pass date range to API calls
- Update DagRunOperations trait and V1/V2 client implementations to
  accept and apply date filter query parameters
- Create DateFilterPopup with interactive calendar navigation
  (h/l: ±day, j/k: ±week, H/L: ±month, Space: select, Tab: toggle
  field, x: clear, Enter: apply)
- Wire date filter through WorkerMessage and worker handlers
- Show active date filter range in the panel title bar
- Add 'd' keybinding and help entry for the date filter command

https://claude.ai/code/session_017JgxKcniaEptjNFaQ8iPbU
@jvanbuel jvanbuel force-pushed the claude/add-dagrun-date-filter-V6y40 branch from ecd0690 to d254bd1 Compare February 21, 2026 18:08
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (4)
src/airflow/traits/dagrun.rs (1)

7-12: Consider deriving PartialEq + Eq to enable filter-change detection

Without these derives, callers cannot cheaply check whether the applied filter actually changed (e.g., to avoid issuing a redundant API call when the user re-applies the same dates). Given the struct contains only Option<time::Date>, both are trivially derivable.

♻️ Proposed refactor
-#[derive(Debug, Clone, Default)]
+#[derive(Debug, Clone, Default, PartialEq, Eq)]
 pub struct DagRunDateFilter {
     pub start_date: Option<Date>,
     pub end_date: Option<Date>,
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/airflow/traits/dagrun.rs` around lines 7 - 12, Add Eq and PartialEq
derives to the DagRunDateFilter struct so callers can cheaply compare filters;
update the struct declaration (DagRunDateFilter with fields start_date and
end_date) to derive PartialEq and Eq in addition to Debug, Clone, Default.
src/app/worker/dagruns.rs (1)

93-94: Post-trigger refresh ignores the active date filter.

handle_trigger_dag_run refreshes the DAG runs list using DagRunDateFilter::default(), which discards any active filter the user may have set. This could cause a brief flash of unfiltered results until the next periodic tick re-applies the correct filter.

Consider threading the user's current date_filter through the TriggerDagRun worker message so the post-trigger refresh respects the active filter.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/worker/dagruns.rs` around lines 93 - 94, handle_trigger_dag_run
currently calls handle_update_dag_runs(..., &DagRunDateFilter::default()), which
drops the user's active filter; modify the TriggerDagRun worker message to carry
the current date_filter (e.g., a DagRunDateFilter field), update places that
construct/send TriggerDagRun to populate that field, and change
handle_trigger_dag_run to forward the provided date_filter to
handle_update_dag_runs instead of using DagRunDateFilter::default(); ensure the
TriggerDagRun struct and its handler signature are updated consistently so the
post-trigger refresh respects the active date filter.
src/app/worker/mod.rs (1)

110-110: Dedup key ignores date_filter — a filter change may be briefly delayed.

The .. wildcard means that if a periodic UpdateDagRuns for the same dag_id is already in-flight when the user applies a new date filter, the immediate refresh request will be silently dropped. The next tick will correct this, so the impact is a brief delay (≤ one refresh interval). This is likely fine, but worth being aware of.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/worker/mod.rs` at line 110, The dedup key for UpdateDagRuns currently
ignores the date_filter because the pattern uses `..`, causing requests with
different filters to collide; change the match arm for `UpdateDagRuns` to
destructure and include the `date_filter` (serialized or Option string) in the
dedup key (e.g., `format!("UpdateDagRuns:{dag_id}:{date_filter}")`) so each
distinct filter produces a unique key; specifically update the match arm that
returns Some(format!(...)) to capture the `date_filter` field from the
`UpdateDagRuns` variant and incorporate it into the formatted key.
src/app/model/popup/dagruns/date_filter.rs (1)

307-325: Range highlighting iterates every day between start and end.

For very large date ranges (e.g., spanning years), this loop adds thousands of entries to CalendarEventStore, though only ~31 are visible. In practice, DAG run filters are unlikely to span years, so this is fine — but if it ever becomes a concern, you could clamp the iteration to the displayed month.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/model/popup/dagruns/date_filter.rs` around lines 307 - 325, The loop
currently iterates every day between self.start_date and self.end_date and adds
each to events via events.add, which can create thousands of entries for
multi-year ranges; instead clamp the iteration to the visible/displayed month
(or a fixed ~31-day window) around the calendar view before looping. Concretely,
compute a visible_start and visible_end based on the current calendar view
derived from self.cursor_date (e.g., first and last day of the displayed month
or a 31-day window centered on self.cursor_date), then set the iteration bounds
to max(range_start, visible_start) and min(range_end, visible_end) and iterate
from that clamped start using d.next_day(), calling events.add only for dates
inside the clamped range (still skipping
self.cursor_date/self.start_date/self.end_date as before).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/airflow/client/v1/dagrun.rs`:
- Around line 28-32: When building the execution_date_lte query in dagrun.rs,
ensure we don't silently drop the upper bound when date_filter.end_date is
Date::MAX: call end.next_day() as before, but if it returns None fall back to
using end itself (i.e., push query.push(("execution_date_lte",
format!("{end}"))) instead of doing nothing); update the block around
date_filter.end_date and the call to next_day() so the "execution_date_lte"
filter is always added using either next_day or the original end value.
- Around line 25-32: The query currently sends date-only strings from
date_filter.start_date and date_filter.end_date (and end.next_day()) for
execution_date_gte/execution_date_lte, but Airflow expects full RFC3339
datetimes; convert the dates to ISO-8601 datetimes with timezone before pushing
to query (e.g., treat start as start_date at 00:00:00+00:00 and use next_day at
00:00:00+00:00 for the end-inclusive bound), using your project's date/time
serializer (e.g., to_rfc3339 / chrono::DateTime formatting) so
execution_date_gte and execution_date_lte are full datetime strings.

In `@src/app/model/popup/dagruns/date_filter.rs`:
- Around line 106-117: The date selection allows start_date and end_date to be
set in any order which can produce an inverted range; update to_date_filter() to
normalize the range by checking self.start_date and self.end_date and swapping
them when start_date > end_date so the returned filter always has start ≤ end;
keep select_current_date() and DateField logic as-is but ensure to_date_filter()
uses the normalized values (refer to to_date_filter, start_date, end_date, and
DateField) before constructing the filter.

---

Duplicate comments:
In `@src/airflow/client/v2/dagrun.rs`:
- Around line 25-31: The date-only values in dagrun.rs are being formatted as
bare YYYY-MM-DD for query params (in the block checking date_filter.start_date
and date_filter.end_date), causing incorrect filtering; update the formatting
for start and next_day to produce full RFC-like datetimes by appending
"T00:00:00+00:00" (e.g., format!("{start}T00:00:00+00:00")), and for the end
branch use the same next_day() -> unwrap_or(end) fallback used in V1 so that
Date::MAX is handled (i.e., compute next_day().unwrap_or(end) and format that to
logical_date_lte); adjust the query pushes for logical_date_gte and
logical_date_lte accordingly.

---

Nitpick comments:
In `@src/airflow/traits/dagrun.rs`:
- Around line 7-12: Add Eq and PartialEq derives to the DagRunDateFilter struct
so callers can cheaply compare filters; update the struct declaration
(DagRunDateFilter with fields start_date and end_date) to derive PartialEq and
Eq in addition to Debug, Clone, Default.

In `@src/app/model/popup/dagruns/date_filter.rs`:
- Around line 307-325: The loop currently iterates every day between
self.start_date and self.end_date and adds each to events via events.add, which
can create thousands of entries for multi-year ranges; instead clamp the
iteration to the visible/displayed month (or a fixed ~31-day window) around the
calendar view before looping. Concretely, compute a visible_start and
visible_end based on the current calendar view derived from self.cursor_date
(e.g., first and last day of the displayed month or a 31-day window centered on
self.cursor_date), then set the iteration bounds to max(range_start,
visible_start) and min(range_end, visible_end) and iterate from that clamped
start using d.next_day(), calling events.add only for dates inside the clamped
range (still skipping self.cursor_date/self.start_date/self.end_date as before).

In `@src/app/worker/dagruns.rs`:
- Around line 93-94: handle_trigger_dag_run currently calls
handle_update_dag_runs(..., &DagRunDateFilter::default()), which drops the
user's active filter; modify the TriggerDagRun worker message to carry the
current date_filter (e.g., a DagRunDateFilter field), update places that
construct/send TriggerDagRun to populate that field, and change
handle_trigger_dag_run to forward the provided date_filter to
handle_update_dag_runs instead of using DagRunDateFilter::default(); ensure the
TriggerDagRun struct and its handler signature are updated consistently so the
post-trigger refresh respects the active date filter.

In `@src/app/worker/mod.rs`:
- Line 110: The dedup key for UpdateDagRuns currently ignores the date_filter
because the pattern uses `..`, causing requests with different filters to
collide; change the match arm for `UpdateDagRuns` to destructure and include the
`date_filter` (serialized or Option string) in the dedup key (e.g.,
`format!("UpdateDagRuns:{dag_id}:{date_filter}")`) so each distinct filter
produces a unique key; specifically update the match arm that returns
Some(format!(...)) to capture the `date_filter` field from the `UpdateDagRuns`
variant and incorporate it into the formatted key.

Comment on lines +25 to +32
if let Some(start) = date_filter.start_date {
query.push(("execution_date_gte", format!("{start}")));
}
if let Some(end) = date_filter.end_date {
// Add one day to make the end date inclusive
if let Some(next_day) = end.next_day() {
query.push(("execution_date_lte", format!("{next_day}")));
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

Airflow REST API v1 execution_date_gte execution_date_lte parameter format date datetime

💡 Result:

For Airflow Stable REST API v1 list endpoints (e.g. GET /api/v1/dags/{dag_id}/dagRuns), the execution_date_gte / execution_date_lte filters are query parameters whose schema is type: string, format: date-time (OpenAPI “date-time”). [1]

That means you should send an RFC 3339 / ISO-8601 datetime with timezone, e.g. Z (UTC) or an offset like +00:00: [2]

  • 2023-02-02T00:00:00Z
  • 2023-02-02T00:00:00+00:00
  • 2023-02-02T00:00:00.123456+00:00 (fractional seconds are fine)

Example:

curl -u airflow:airflow \
  "http://localhost:8080/api/v1/dags/demand_forecast/dagRuns?execution_date_gte=2023-02-02T00:00:00Z&execution_date_lte=2023-02-03T00:00:00Z"

Also: don’t put these in the JSON body of a GET; they need to be in the URL query string. [3]

Sources: [1] [2] [3]


🌐 Web query:

Airflow 2.x /api/v1 dagRuns list endpoint date filter format requirements

💡 Result:

For Airflow 2.x GET /api/v1/dags/{dag_id}/dagRuns, the “date” filters are query parameters (not JSON body) and must be passed as an ISO-8601 / RFC3339 date-time string (i.e., OpenAPI format: date-time, including a timezone like Z or an offset). (fossies.org)

Which filter params (2.x)

Depending on your Airflow 2.x minor version, you’ll typically use these query params (all date-time):

  • logical_date_gte, logical_date_lte (newer 2.x; execution_date was replaced by logical_date) (fossies.org)
  • start_date_gte/lte, end_date_gte/lte, run_after_gte/lte (fossies.org)
    (Older 2.x may still document/use execution_date_gte/lte; newer versions moved to logical_date_*.) (astronomer.io)

Accepted timestamp examples

Use RFC3339 like:

  • 2024-10-01T13:00:00Z
  • 2024-10-01T13:00:00+00:00
    Both Z and +00:00 forms are accepted in inputs in newer releases. (github.com)

Example request

curl -X GET \
  "http://localhost:8080/api/v1/dags/my_dag/dagRuns?logical_date_gte=2024-10-01T00:00:00Z&logical_date_lte=2024-10-31T23:59:59Z"

Note: if you include an offset with + (e.g. +00:00) in a URL, it should be URL-encoded (otherwise + may be treated as a space).

Citations:


🏁 Script executed:

# Search the codebase to understand the DagRunDateFilter type and how dates are handled
rg -A 5 "struct DagRunDateFilter" src/

Repository: jvanbuel/flowrs

Length of output: 364


🏁 Script executed:

# Check the time crate version and Date Display implementation
cat -n Cargo.toml | grep -A 2 "time"

Repository: jvanbuel/flowrs

Length of output: 158


Date format mismatch — Airflow /api/v1 requires full datetime, not date-only string

The current code sends date-only strings (e.g., 2023-02-02) for execution_date_gte/lte parameters, but the Airflow v1 REST API spec defines these as format: date-time, requiring RFC3339 / ISO-8601 datetime with timezone (e.g., 2023-02-02T00:00:00Z or 2023-02-02T00:00:00+00:00). A bare date will be rejected by the API.

Fix by appending the time component:

Proposed fix
-        if let Some(start) = date_filter.start_date {
-            query.push(("execution_date_gte", format!("{start}")));
-        }
-        if let Some(end) = date_filter.end_date {
-            // Add one day to make the end date inclusive
-            if let Some(next_day) = end.next_day() {
-                query.push(("execution_date_lte", format!("{next_day}")));
-            }
-        }
+        if let Some(start) = date_filter.start_date {
+            query.push(("execution_date_gte", format!("{start}T00:00:00Z")));
+        }
+        if let Some(end) = date_filter.end_date {
+            // Add one day to make the end date inclusive
+            if let Some(next_day) = end.next_day() {
+                query.push(("execution_date_lte", format!("{next_day}T00:00:00Z")));
+            }
+        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if let Some(start) = date_filter.start_date {
query.push(("execution_date_gte", format!("{start}")));
}
if let Some(end) = date_filter.end_date {
// Add one day to make the end date inclusive
if let Some(next_day) = end.next_day() {
query.push(("execution_date_lte", format!("{next_day}")));
}
if let Some(start) = date_filter.start_date {
query.push(("execution_date_gte", format!("{start}T00:00:00Z")));
}
if let Some(end) = date_filter.end_date {
// Add one day to make the end date inclusive
if let Some(next_day) = end.next_day() {
query.push(("execution_date_lte", format!("{next_day}T00:00:00Z")));
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/airflow/client/v1/dagrun.rs` around lines 25 - 32, The query currently
sends date-only strings from date_filter.start_date and date_filter.end_date
(and end.next_day()) for execution_date_gte/execution_date_lte, but Airflow
expects full RFC3339 datetimes; convert the dates to ISO-8601 datetimes with
timezone before pushing to query (e.g., treat start as start_date at
00:00:00+00:00 and use next_day at 00:00:00+00:00 for the end-inclusive bound),
using your project's date/time serializer (e.g., to_rfc3339 / chrono::DateTime
formatting) so execution_date_gte and execution_date_lte are full datetime
strings.

Comment on lines +28 to +32
if let Some(end) = date_filter.end_date {
// Add one day to make the end date inclusive
if let Some(next_day) = end.next_day() {
query.push(("execution_date_lte", format!("{next_day}")));
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Silent end-date filter drop when end_date is time::Date::MAX

When end_date == Date::MAX (9999-12-31), next_day() returns None and the upper-bound filter is silently dropped, making the query unbounded upward even though the user explicitly selected an end date. While practically unreachable through a calendar picker, the silent fallback is worth making explicit.

💡 Proposed fix — fall back to the selected end date itself
         if let Some(end) = date_filter.end_date {
             // Add one day to make the end date inclusive
-            if let Some(next_day) = end.next_day() {
-                query.push(("execution_date_lte", format!("{next_day}T00:00:00+00:00")));
-            }
+            let bound = end.next_day().unwrap_or(end);
+            query.push(("execution_date_lte", format!("{bound}T00:00:00+00:00")));
         }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if let Some(end) = date_filter.end_date {
// Add one day to make the end date inclusive
if let Some(next_day) = end.next_day() {
query.push(("execution_date_lte", format!("{next_day}")));
}
if let Some(end) = date_filter.end_date {
// Add one day to make the end date inclusive
let bound = end.next_day().unwrap_or(end);
query.push(("execution_date_lte", format!("{bound}")));
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/airflow/client/v1/dagrun.rs` around lines 28 - 32, When building the
execution_date_lte query in dagrun.rs, ensure we don't silently drop the upper
bound when date_filter.end_date is Date::MAX: call end.next_day() as before, but
if it returns None fall back to using end itself (i.e., push
query.push(("execution_date_lte", format!("{end}"))) instead of doing nothing);
update the block around date_filter.end_date and the call to next_day() so the
"execution_date_lte" filter is always added using either next_day or the
original end value.

Comment on lines +106 to +117
fn select_current_date(&mut self) {
match self.active_field {
DateField::Start => {
self.start_date = Some(self.cursor_date);
// Auto-advance to end date selection
self.active_field = DateField::End;
}
DateField::End => {
self.end_date = Some(self.cursor_date);
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

No validation that start_date ≤ end_date.

A user can Tab back to the Start field and select a date after the End date (or vice versa). to_date_filter() will produce a filter where start > end, which will likely yield zero results from the API. The range rendering (Line 309) handles this by swapping, but the filter itself is not normalized.

Consider swapping the dates in to_date_filter() if they're inverted:

🛡️ Proposed fix
     pub fn to_date_filter(&self) -> DagRunDateFilter {
+        // Normalize so start <= end
+        let (start, end) = match (self.start_date, self.end_date) {
+            (Some(s), Some(e)) if s > e => (Some(e), Some(s)),
+            other => other,
+        };
         DagRunDateFilter {
-            start_date: self.start_date,
-            end_date: self.end_date,
+            start_date: start,
+            end_date: end,
         }
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/model/popup/dagruns/date_filter.rs` around lines 106 - 117, The date
selection allows start_date and end_date to be set in any order which can
produce an inverted range; update to_date_filter() to normalize the range by
checking self.start_date and self.end_date and swapping them when start_date >
end_date so the returned filter always has start ≤ end; keep
select_current_date() and DateField logic as-is but ensure to_date_filter() uses
the normalized values (refer to to_date_filter, start_date, end_date, and
DateField) before constructing the filter.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants