Repository: apache/airflow

Issue:
Auto-refresh doesn't take into account the selected date
### Apache Airflow version

2.1.3

### Operating System

Debian GNU/Linux 9 (stretch)

### Versions of Apache Airflow Providers

_No response_

### Deployment

Other Docker-based deployment

### Deployment details

_No response_

### What happened

In the DAG tree view, if I select a custom date in the date filter (top left corner) and press "update", DAG runs are correctly filtered to the selected date and number of runs.
 
However, if the "auto-refresh" toggle is on, when the next tick refresh happens, the date filter is no longer taken into account and the UI displays the actual **latest** x DAG runs status. However, neither the header dates (45° angle) nor the date filter reflect this new time window 

I investigated in the network inspector and it seems that the xhr request that fetches dag runs status doesn't contain a date parameter and thus always fetch the latest DAG run data

### What you expected to happen

I expect that the auto-refresh feature preserves the selected time window

### How to reproduce

Open a DAG with at least 20 dag runs
Make sure autorefresh is disabled
Select a filter date earlier than the 10th dag run start date and a "number of runs" value of 10, press "update"
The DAG tree view should now be focused on the 10 first dag runs
Now toggle autorefresh and wait for next tick
The DAG tree view will now display status of the latest 10 runs but the header dates will still reflect the old start dates

### Anything else

_No response_

### Are you willing to submit PR?

- [X] Yes I am willing to submit a PR!

### Code of Conduct

- [X] I agree to follow this project's [Code of Conduct](https://github.com/apache/airflow/blob/main/CODE_OF_CONDUCT.md)



Discussion:
Thanks for opening your first issue here! Be sure to follow the issue template!

Makes sense to me. It should be relatively easily to just pass the date in `tree.js` [here](https://github.com/apache/airflow/blob/main/airflow/www/static/js/tree.js#L433). I believe the webserver code is already built to handle the `base_date`
Yep exactly, I looked around and I was planning on adding the base date as a meta tag in the html template in order to match the current implementation. If that's fine by you I'll submit a PR in the next couple of days :)
I will add my observation :)
Refresh button also cause this problem.
Raw view (without day/time filter in he left corner:
![Zrzut ekranu 2021-10-30 111252](https://user-images.githubusercontent.com/60385441/139527335-9b482ed4-5f0f-4761-9b49-42c058e48db5.png)
After filter apply (button update)
![Zrzut ekranu 2021-10-30 111309](https://user-images.githubusercontent.com/60385441/139527337-dea3411f-1b17-44f9-9fad-f808aae46f25.png)
After refresh button click
![Zrzut ekranu 2021-10-30 111329](https://user-images.githubusercontent.com/60385441/139527334-887429ef-5310-4bf8-af1f-0cb6c0b18594.png)

Legend respects day/time filter but taskInstances not :)
@peloyeje do you still want to take this on or should I finish this out? Quite a bit changed with #18675
@bbovenzi sorry for my late reply, yes please go ahead, you're right it may be easier if you handle this :)
Great job on https://github.com/apache/airflow/pull/18675 btw !

Resolving patch:
diff --git a/airflow/www/views.py b/airflow/www/views.py
--- a/airflow/www/views.py
+++ b/airflow/www/views.py
@@ -288,7 +288,6 @@ def get_summary(dag_run, children):
         }
 
     group_summaries = [get_summary(dr, children) for dr in dag_runs]
-    group_summaries.reverse()
 
     return {
         'id': task_group.group_id,
@@ -2256,6 +2255,7 @@ def tree(self, session=None):
             .limit(num_runs)
             .all()
         )
+        dag_runs.reverse()
         encoded_runs = [wwwutils.encode_dag_run(dr) for dr in dag_runs]
         dag_run_dates = {dr.execution_date: alchemy_to_dict(dr) for dr in dag_runs}
 
@@ -3001,6 +3001,7 @@ def tree_data(self):
                 .limit(num_runs)
                 .all()
             )
+            dag_runs.reverse()
             encoded_runs = [wwwutils.encode_dag_run(dr) for dr in dag_runs]
             dag_run_dates = {dr.execution_date: alchemy_to_dict(dr) for dr in dag_runs}
             min_date = min(dag_run_dates, default=None)


Test patch:
diff --git a/airflow/www/static/js/tree/useTreeData.test.js b/airflow/www/static/js/tree/useTreeData.test.js
--- a/airflow/www/static/js/tree/useTreeData.test.js
+++ b/airflow/www/static/js/tree/useTreeData.test.js
@@ -20,11 +20,11 @@
 import { renderHook } from '@testing-library/react-hooks';
 import useTreeData from './useTreeData';
 
-/* global describe, test, expect */
+/* global describe, test, expect, fetch, beforeEach */
 
 global.autoRefreshInterval = 5;
 
-const treeData = {
+const pendingTreeData = {
   groups: {},
   dag_runs: [
     {
@@ -41,9 +41,18 @@ const treeData = {
   ],
 };
 
+const finalTreeData = {
+  groups: {},
+  dag_runs: [{ ...pendingTreeData.dag_runs[0], state: 'failed' }],
+};
+
 describe('Test useTreeData hook', () => {
+  beforeEach(() => {
+    fetch.resetMocks();
+  });
+
   test('data is valid camelcase json', () => {
-    global.treeData = JSON.stringify(treeData);
+    global.treeData = JSON.stringify(pendingTreeData);
 
     const { result } = renderHook(() => useTreeData());
     const { data, isRefreshOn, onToggleRefresh } = result.current;
@@ -55,20 +64,23 @@ describe('Test useTreeData hook', () => {
     expect(typeof onToggleRefresh).toBe('function');
   });
 
-  test('data with an unfinished state should have refresh on by default', () => {
-    global.treeData = JSON.stringify(treeData);
+  test('queued run should have refreshOn by default and then turn off when run failed', async () => {
+    // return a dag run of failed during refresh
+    fetch.mockResponse(JSON.stringify(finalTreeData));
+    global.treeData = JSON.stringify(pendingTreeData);
+    global.autoRefreshInterval = 0.1;
 
-    const { result } = renderHook(() => useTreeData());
-    const { isRefreshOn } = result.current;
+    const { result, waitFor } = renderHook(() => useTreeData());
 
-    expect(isRefreshOn).toBe(true);
+    expect(result.current.isRefreshOn).toBe(true);
+
+    await waitFor(() => expect(fetch).toBeCalled());
+
+    expect(result.current.isRefreshOn).toBe(false);
   });
 
   test('data with a finished state should have refresh off by default', () => {
-    global.treeData = JSON.stringify({
-      groups: {},
-      dag_runs: [{ ...treeData.dag_runs[0], state: 'failed' }],
-    });
+    global.treeData = JSON.stringify(finalTreeData);
 
     const { result } = renderHook(() => useTreeData());
     const { isRefreshOn } = result.current;