diff --git a/airflow/www/templates/airflow/dags.html b/airflow/www/templates/airflow/dags.html index 3f4b9f69b525e..f4684c8300aa7 100644 --- a/airflow/www/templates/airflow/dags.html +++ b/airflow/www/templates/airflow/dags.html @@ -103,13 +103,11 @@

DAGs

- {% 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 %} +
+ + + +
@@ -309,6 +307,21 @@

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=" + encodeURIComponent(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 d5ac9808fffaa..a1210e2c08728 100644 --- a/airflow/www/views.py +++ b/airflow/www/views.py @@ -403,6 +403,33 @@ 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/www/test_views.py b/tests/www/test_views.py index e2ab673db05f1..ce593da003a8d 100644 --- a/tests/www/test_views.py +++ b/tests/www/test_views.py @@ -490,6 +490,10 @@ def test_graph(self): resp = self.client.get(url, follow_redirects=True) self.check_content_in_response('runme_1', resp) + def test_last_dagruns(self): + resp = self.client.get('last_dagruns', follow_redirects=True) + self.check_content_in_response('example_bash_operator', resp) + def test_tree(self): url = 'tree?dag_id=example_bash_operator' resp = self.client.get(url, follow_redirects=True)