diff --git a/airflow/www/templates/airflow/dags.html b/airflow/www/templates/airflow/dags.html
index e3eda43cad9be..0a7a6ec2a4791 100644
--- a/airflow/www/templates/airflow/dags.html
+++ b/airflow/www/templates/airflow/dags.html
@@ -118,11 +118,15 @@
DAGs
-
-
-
-
-
+ {% if dag %}
+ {% set last_run = dag.get_last_dagrun(include_externally_triggered=True) %}
+ {% if last_run and last_run.execution_date %}
+
+ {{ last_run.execution_date.strftime("%Y-%m-%d %H:%M") }}
+
+
+ {% endif %}
+ {% endif %}
|
@@ -314,24 +318,6 @@ DAGs
}
});
});
- d3.json("{{ url_for('airflow.last_dagruns') }}", function(error, json) {
- for(var safe_dag_id in json) {
- dag_id = json[safe_dag_id].dag_id;
- last_run = json[safe_dag_id].last_run;
- g = d3.select('div#last-run-' + safe_dag_id)
-
- g.selectAll('a')
- .attr("href", "{{ url_for('airflow.graph') }}?dag_id=" + dag_id + "&execution_date=" + last_run)
- .text(last_run);
-
- g.selectAll('span')
- .attr("data-original-title", "Start Date: " + last_run)
- .style('display', null);
-
- g.selectAll(".loading-last-run").remove();
- }
- d3.selectAll(".loading-last-run").remove();
- });
d3.json("{{ url_for('airflow.dag_stats') }}", function(error, json) {
for(var dag_id in json) {
states = json[dag_id];
diff --git a/airflow/www/views.py b/airflow/www/views.py
index 206caea7b948b..fc9e06abd1828 100644
--- a/airflow/www/views.py
+++ b/airflow/www/views.py
@@ -645,26 +645,6 @@ def task_stats(self, session=None):
})
return wwwutils.json_response(payload)
- @expose('/last_dagruns')
- @login_required
- @provide_session
- def last_dagruns(self, session=None):
- DagRun = models.DagRun
-
- dags_to_latest_runs = dict(session.query(
- DagRun.dag_id, sqla.func.max(DagRun.execution_date).label('execution_date'))
- .group_by(DagRun.dag_id).all())
-
- payload = {}
- for dag in dagbag.dags.values():
- if dag.dag_id in dags_to_latest_runs and dags_to_latest_runs[dag.dag_id]:
- payload[dag.safe_dag_id] = {
- 'dag_id': dag.dag_id,
- 'last_run': dags_to_latest_runs[dag.dag_id].strftime("%Y-%m-%d %H:%M")
- }
-
- return wwwutils.json_response(payload)
-
@expose('/code')
@login_required
def code(self):
diff --git a/airflow/www_rbac/templates/airflow/dags.html b/airflow/www_rbac/templates/airflow/dags.html
index b071d0ae7b822..5f492780d56ea 100644
--- a/airflow/www_rbac/templates/airflow/dags.html
+++ b/airflow/www_rbac/templates/airflow/dags.html
@@ -119,11 +119,15 @@ DAGs
-
-
-
-
-
+ {% if dag %}
+ {% set last_run = dag.get_last_dagrun(include_externally_triggered=True) %}
+ {% if last_run and last_run.execution_date %}
+
+ {{ last_run.execution_date.strftime("%Y-%m-%d %H:%M") }}
+
+
+ {% endif %}
+ {% endif %}
|
@@ -314,24 +318,6 @@ DAGs
}
});
});
- d3.json("{{ url_for('Airflow.last_dagruns') }}", function(error, json) {
- for(var safe_dag_id in json) {
- dag_id = json[safe_dag_id].dag_id;
- last_run = json[safe_dag_id].last_run;
- g = d3.select('div#last-run-' + safe_dag_id)
-
- g.selectAll('a')
- .attr("href", "{{ url_for('Airflow.graph') }}?dag_id=" + dag_id + "&execution_date=" + last_run)
- .text(last_run);
-
- g.selectAll('span')
- .attr("data-original-title", "Start Date: " + last_run)
- .style('display', null);
-
- g.selectAll(".loading-last-run").remove();
- }
- d3.selectAll(".loading-last-run").remove();
- });
d3.json("{{ url_for('Airflow.dag_stats') }}", function(error, json) {
for(var dag_id in json) {
states = json[dag_id];
diff --git a/airflow/www_rbac/views.py b/airflow/www_rbac/views.py
index b47cb0ec14b2c..8d0a8b0ea8afc 100644
--- a/airflow/www_rbac/views.py
+++ b/airflow/www_rbac/views.py
@@ -384,33 +384,6 @@ def task_stats(self, session=None):
})
return wwwutils.json_response(payload)
- @expose('/last_dagruns')
- @has_access
- @provide_session
- def last_dagruns(self, session=None):
- DagRun = models.DagRun
-
- filter_dag_ids = appbuilder.sm.get_accessible_dag_ids()
-
- if not filter_dag_ids:
- return
-
- dags_to_latest_runs = dict(session.query(
- DagRun.dag_id, sqla.func.max(DagRun.execution_date).label('execution_date'))
- .group_by(DagRun.dag_id).all())
-
- payload = {}
- for dag in dagbag.dags.values():
- dag_accessible = 'all_dags' in filter_dag_ids or dag.dag_id in filter_dag_ids
- if (dag_accessible and dag.dag_id in dags_to_latest_runs and
- dags_to_latest_runs[dag.dag_id]):
- payload[dag.safe_dag_id] = {
- 'dag_id': dag.dag_id,
- 'last_run': dags_to_latest_runs[dag.dag_id].strftime("%Y-%m-%d %H:%M")
- }
-
- return wwwutils.json_response(payload)
-
@expose('/code')
@has_dag_access(can_dag_read=True)
@has_access
diff --git a/tests/core.py b/tests/core.py
index b7301b237805e..6b9cbbf072cdc 100644
--- a/tests/core.py
+++ b/tests/core.py
@@ -39,6 +39,7 @@
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from numpy.testing import assert_array_almost_equal
+from six.moves.urllib.parse import urlencode
from time import sleep
from airflow import configuration
@@ -1846,6 +1847,17 @@ def test_index(self):
self.assertIn("DAGs", resp_html)
self.assertIn("example_bash_operator", resp_html)
+ # The HTML should contain data for the last-run. A link to the specific run,
+ # and the text of the date.
+ url = "/admin/airflow/graph?" + urlencode({
+ "dag_id": self.dag_python.dag_id,
+ "execution_date": self.dagrun_python.execution_date,
+ }).replace("&", "&")
+ self.assertIn(url, resp_html)
+ self.assertIn(
+ self.dagrun_python.execution_date.strftime("%Y-%m-%d %H:%M"),
+ resp_html)
+
def test_query(self):
response = self.app.get('/admin/queryview/')
self.assertIn("Ad Hoc Query", response.data.decode('utf-8'))
@@ -1929,9 +1941,6 @@ def test_dag_views(self):
response = self.app.get(
'/admin/airflow/task_stats')
self.assertIn("example_bash_operator", response.data.decode('utf-8'))
- response = self.app.get(
- '/admin/airflow/last_dagruns')
- self.assertIn("example_python_operator", response.data.decode('utf-8'))
url = (
"/admin/airflow/success?task_id=print_the_context&"
"dag_id=example_python_operator&upstream=false&downstream=false&"