Skip to content

UI: Fix Gantt tooltip showing wrong end date on queued/scheduled bars#68570

Open
Aaryan123456679 wants to merge 1 commit into
apache:mainfrom
Aaryan123456679:fix/gantt-tooltip-end-date-68174
Open

UI: Fix Gantt tooltip showing wrong end date on queued/scheduled bars#68570
Aaryan123456679 wants to merge 1 commit into
apache:mainfrom
Aaryan123456679:fix/gantt-tooltip-end-date-68174

Conversation

@Aaryan123456679

@Aaryan123456679 Aaryan123456679 commented Jun 15, 2026

Copy link
Copy Markdown

The Gantt tooltip showed the wrong End Date when hovering over the queued or scheduled segment of a task bar: it reported the end of that segment (e.g. the instant queueing ended) rather than the task's actual end.

This was a regression from #68176, which fixed the Start Date by carrying the task's real start_date on every segment of a try (start_when) but left the End Date derived from each segment's own bounds (max_end_date = segment.x[1]).

This PR mirrors that approach for the end: each segment of a try now carries the task's effective end (end_date, or "now" while the task is still running) as end_when, and the tooltip uses it for the End Date. As a result, the scheduled, queued, and execution bars of the same try all report a consistent Start Date, End Date, and duration.

Tests added in Gantt/utils.test.ts assert that start_when/end_when are carried consistently across all segments of a finished task and of a running task.

closes: #68174


Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Opus 4.8)

Generated-by: Claude Code (Opus 4.8) following the guidelines

The tooltip on the queued and scheduled segments of a Gantt bar reported
the end of that segment (e.g. the moment queueing ended) as the task's
End Date, instead of the task's actual end. This was a regression from
the start-date fix in apache#68176, which made the Start Date consistent across
segments but left the End Date per-segment.

Carry the task's effective end (end_date, or "now" while running) on every
segment of a try as `end_when`, mirroring `start_when`, and use it for the
tooltip's End Date so all segments of a try report the same start and end.

closes: apache#68174
@boring-cyborg boring-cyborg Bot added the area:UI Related to UI/UX. For Frontend Developers. label Jun 15, 2026
@boring-cyborg

boring-cyborg Bot commented Jun 15, 2026

Copy link
Copy Markdown

Congratulations on your first Pull Request and welcome to the Apache Airflow community! If you have any issues or are unsure about any anything please check our Contributors' Guide
Here are some useful points:

  • Pay attention to the quality of your code (ruff, mypy and type annotations). Our prek-hooks will help you with that.
  • In case of a new feature add useful documentation (in docstrings or in docs/ directory). Adding a new operator? Check this short guide Consider adding an example Dag that shows how users should use it.
  • Consider using Breeze environment for testing locally, it's a heavy docker but it ships with a working Airflow and a lot of integrations.
  • Be patient and persistent. It might take some time to get a review or get the final approval from Committers.
  • Please follow ASF Code of Conduct for all communication including (but not limited to) comments on Pull Requests, Mailing list and Slack.
  • Be sure to read the Airflow Coding style.
  • Always keep your Pull Requests rebased, otherwise your build might fail due to changes not related to your commits.
    Apache Airflow is a community-driven project and together we are making it better 🚀.
    In case of doubts contact the developers at:
    Mailing List: dev@airflow.apache.org
    Slack: https://s.apache.org/airflow-slack

@eladkal

eladkal commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

can you share before/after images?

@eladkal eladkal requested a review from jscheffl June 15, 2026 13:22
@Aaryan123456679

Copy link
Copy Markdown
Author
after before

@eladkal Pls find attached the screenshots.

@eladkal eladkal added this to the Airflow 3.3.0 milestone Jun 15, 2026
@eladkal eladkal added the type:bug-fix Changelog: Bug Fixes label Jun 15, 2026
@Aaryan123456679

Copy link
Copy Markdown
Author

Hi @eladkal , any update on this?

@potiuk potiuk added the ready for maintainer review Set after triaging when all criteria pass. label Jun 22, 2026

@pierrejeambrun pierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks @Aaryan123456679 — fix mirrors the existing start_when plumbing cleanly and the screenshots make the win obvious. One small nit on the new running-task test below.

for (const segment of result) {
expect(segment.end_when).toBe(firstEnd);
expect(segment.end_when).not.toBeUndefined();
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could you tighten this to pin the actual value of end_when, not just that it's consistent across segments? With vi.useFakeTimers() + vi.setSystemTime(...) you can also assert end_when matches that fixed "now" — otherwise a regression returning a stale or zero timestamp would slip past.

Suggested change
}
it("uses the current time as end_when on every segment while the task is still running", () => {
vi.useFakeTimers();
vi.setSystemTime(new Date("2024-03-14T10:02:00+00:00"));
try {
const result = transformGanttData({
allTries: [
{
end_date: null,
is_mapped: false,
queued_dttm: "2024-03-14T09:59:00+00:00",
scheduled_dttm: null,
start_date: "2024-03-14T10:00:00+00:00",
state: "running",
task_display_name: "task_1",
task_id: "task_1",
try_number: 1,
},
],
flatNodes: [{ depth: 0, id: "task_1", is_mapped: false, label: "task_1" }],
gridSummaries: [],
});
const expectedEnd = new Date("2024-03-14T10:02:00+00:00").toISOString();
for (const segment of result) {
expect(segment.end_when).toBe(expectedEnd);
}
} finally {
vi.useRealTimers();
}
});

@pierrejeambrun pierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

One more thing on top of the test nit — the new end_when line is asymmetric with start_when in two ways that I think can be smoothed out together.

...(scheduledMs === undefined ? {} : { scheduled_when: scheduledDttm }),
...(queuedMs === undefined ? {} : { queued_when: queuedDttm }),
...(startDate === null ? {} : { start_when: startDate }),
...(startDate === null && !hasTaskRunning ? {} : { end_when: dayjs(endMs).toISOString() }),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

These two lines aren't symmetric with each other:

  • Gate: start_when skips only when startDate === null; end_when adds && !hasTaskRunning. The extra branch only fires for queued/scheduled tasks (isStatePending is true) with no start_date, where the tooltip would then show Start Date = the bar's own start (segment fallback) + End Date = Date.now(). Two different scales in the same tooltip.
  • Value: start_when keeps the raw API string ("2024-03-14T10:00:00+00:00"); end_when is re-serialized via dayjs(endMs).toISOString() to "...Z" with .000 millis. The test even pins this skew. Renders fine because dayjs reparses, but it's needless and it's the reason the tryWhenForTooltip block had to move below endMs.

Suggest collapsing both into a single symmetric form — derive an effectiveEndDate and gate on it like start_when does on startDate:

Suggested change
...(startDate === null && !hasTaskRunning ? {} : { end_when: dayjs(endMs).toISOString() }),
const effectiveEndDate = hasTaskRunning ? new Date().toISOString() : endDate;
// Include scheduled/queued/start/end times in tooltip data whenever the timestamps exist.
// start_when/end_when are carried on every segment of a try so the tooltip reports the
// task's actual start and end on the scheduled and queued bars too, not just the
// execution bar's own bounds.
const tryWhenForTooltip = {
...(scheduledMs === undefined ? {} : { scheduled_when: scheduledDttm }),
...(queuedMs === undefined ? {} : { queued_when: queuedDttm }),
...(startDate === null ? {} : { start_when: startDate }),
...(effectiveEndDate === null ? {} : { end_when: effectiveEndDate }),
};

Then the block doesn't need to live below endMs anymore (no ordering dependency) and finished tasks keep the API's raw end_date string. The test for the finished task can drop the new Date(...).toISOString() wrapping and assert against the raw "2024-03-14T10:05:00+00:00" like it does for start_when.

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

Labels

area:UI Related to UI/UX. For Frontend Developers. ready for maintainer review Set after triaging when all criteria pass. type:bug-fix Changelog: Bug Fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Grid pop-up of start/queue time is inconsistent

4 participants