Skip to content

Commit

Permalink
UX Enhancement: Separate actions from links in DAG navigation (apache…
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanahamilton authored Jul 20, 2020
1 parent 9c518fe commit 273e28c
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 104 deletions.
157 changes: 68 additions & 89 deletions airflow/www/templates/airflow/dag.html
Original file line number Diff line number Diff line change
Expand Up @@ -55,73 +55,56 @@ <h4 class="pull-right">
{% else %}
{% set execution_date_arg = request.args.get('execution_date') %}
{% endif %}
<ul class="nav nav-pills">
{% if dag.parent_dag is defined and dag.parent_dag %}
<li class="never_active"><a href="{{ url_for('Airflow.' + dag.default_view, dag_id=dag.parent_dag.dag_id, base_date=base_date_arg, execution_date=execution_date_arg) }}">
<div class="row">
<div class="col-md-10">
<ul class="nav nav-pills">
{% if dag.parent_dag is defined and dag.parent_dag %}
<li class="never_active"><a href="{{ url_for('Airflow.' + dag.default_view, dag_id=dag.parent_dag.dag_id, base_date=base_date_arg, execution_date=execution_date_arg) }}">
<span class="glyphicon glyphicon-arrow-left" aria-hidden="true"></span>
Back to {{ dag.parent_dag.dag_id }}</a>
</li>
{% endif %}
<li><a href="{{ url_for('Airflow.graph', dag_id=dag.dag_id, root=root, num_runs=num_runs_arg, base_date=base_date_arg, execution_date=execution_date_arg) }}">
<span class="glyphicon glyphicon-certificate" aria-hidden="true"></span>
Graph View</a></li>
<li><a href="{{ url_for('Airflow.tree', dag_id=dag.dag_id, num_runs=num_runs_arg, root=root, base_date=base_date_arg) }}">
<span class="glyphicon glyphicon-tree-deciduous" aria-hidden="true"></span>
Tree View
</a></li>
<li><a href="{{ url_for('Airflow.duration', dag_id=dag.dag_id, days=30, root=root, num_runs=num_runs_arg, base_date=base_date_arg) }}">
<span class="glyphicon glyphicon-stats" aria-hidden="true"></span>
Task Duration
</a></li>
<li><a href="{{ url_for('Airflow.tries', dag_id=dag.dag_id, days=30, root=root, num_runs=num_runs_arg, base_date=base_date_arg) }}">
<span class="glyphicon glyphicon-duplicate" aria-hidden="true"></span>
Task Tries
</a></li>
<li>
<a href="{{ url_for('Airflow.landing_times', dag_id=dag.dag_id, days=30, root=root, num_runs=num_runs_arg, base_date=base_date_arg) }}">
<span class="glyphicon glyphicon-plane" aria-hidden="true"></span>
Landing Times
</a>
</li>
<li>
<a href="{{ url_for('Airflow.gantt', dag_id=dag.dag_id, root=root, num_runs=num_runs_arg, base_date=base_date_arg, execution_date=execution_date_arg) }}">
<span class="glyphicon glyphicon-align-left" aria-hidden="true"></span>
<i class="icon-align-left"></i>
Gantt
</a>
</li>
<li>
<a href="{{ url_for('Airflow.dag_details', dag_id=dag.dag_id) }}">
<span class="glyphicon glyphicon-list" aria-hidden="true"></span>
Details
</a>
</li>
<li>
<a href="{{ url_for('Airflow.code', dag_id=dag.dag_id, root=root) }}">
<span class="glyphicon glyphicon-file" aria-hidden="true"></span>
Code
</a>
</li>
<li>
<a href="{{ url_for('Airflow.trigger', dag_id=dag.dag_id, origin=url_for('Airflow.' + dag.default_view, dag_id=dag.dag_id)) }}">
<span class="glyphicon glyphicon-play-circle" aria-hidden="true"></span>
Trigger DAG
</a>
</li>
<li>
<a href="{{ url_for('Airflow.refresh', dag_id=dag.dag_id) }}" title="Refresh" onclick="postAsForm(this.href); return false">
<span class="glyphicon glyphicon-refresh" aria-hidden="true"></span>
Refresh
</a>
</li>
<li>
<a href="{{ url_for('Airflow.delete', dag_id=dag.dag_id) }}"
onclick="return confirmDeleteDag(this, '{{ dag.safe_dag_id }}')">
<span class="glyphicon glyphicon-remove-circle" style="color:red" aria-hidden="true"></span>
Delete
</a>
</li>
</ul>
Back to {{ dag.parent_dag.dag_id }}</a></li>
{% endif %}
<li><a href="{{ url_for('Airflow.tree', dag_id=dag.dag_id, num_runs=num_runs_arg, root=root, base_date=base_date_arg) }}">
<span class="glyphicon glyphicon-tree-deciduous" aria-hidden="true"></span>
Tree View
</a></li>
<li><a href="{{ url_for('Airflow.graph', dag_id=dag.dag_id, root=root, num_runs=num_runs_arg, base_date=base_date_arg, execution_date=execution_date_arg) }}">
<span class="glyphicon glyphicon-certificate" aria-hidden="true"></span>
Graph View</a></li>
<li><a href="{{ url_for('Airflow.duration', dag_id=dag.dag_id, days=30, root=root, num_runs=num_runs_arg, base_date=base_date_arg) }}">
<span class="glyphicon glyphicon-stats" aria-hidden="true"></span>
Task Duration</a></li>
<li><a href="{{ url_for('Airflow.tries', dag_id=dag.dag_id, days=30, root=root, num_runs=num_runs_arg, base_date=base_date_arg) }}">
<span class="glyphicon glyphicon-duplicate" aria-hidden="true"></span>
Task Tries</a></li>
<li><a href="{{ url_for('Airflow.landing_times', dag_id=dag.dag_id, days=30, root=root, num_runs=num_runs_arg, base_date=base_date_arg) }}">
<span class="glyphicon glyphicon-plane" aria-hidden="true"></span>
Landing Times</a></li>
<li><a href="{{ url_for('Airflow.gantt', dag_id=dag.dag_id, root=root, num_runs=num_runs_arg, base_date=base_date_arg, execution_date=execution_date_arg) }}">
<span class="glyphicon glyphicon-align-left" aria-hidden="true"></span>
Gantt</a></li>
<li><a href="{{ url_for('Airflow.dag_details', dag_id=dag.dag_id) }}">
<span class="glyphicon glyphicon-list" aria-hidden="true"></span>
Details</a></li>
<li><a href="{{ url_for('Airflow.code', dag_id=dag.dag_id, root=root) }}">
<span class="glyphicon glyphicon-file" aria-hidden="true"></span>
Code</a></li>
</ul>
</div>
<div class="col-md-2">
<div class="btn-group pull-right">
<a href="{{ url_for('Airflow.trigger', dag_id=dag.dag_id, origin=url_for('Airflow.' + dag.default_view, dag_id=dag.dag_id)) }}" title="Trigger DAG" aria-label="Trigger DAG" class="btn btn-default">
<span class="glyphicon glyphicon-play" aria-hidden="true"></span>
</a>
<a href="{{ url_for('Airflow.refresh', dag_id=dag.dag_id) }}" title="Refresh DAG" aria-label="Refresh DAG" onclick="postAsForm(this.href); return false" class="btn btn-default">
<span class="glyphicon glyphicon-refresh" aria-hidden="true"></span>
</a>
<a href="{{ url_for('Airflow.delete', dag_id=dag.dag_id) }}" title="Delete&nbsp;DAG" class="btn btn-default"
onclick="return confirmDeleteDag(this, '{{ dag.safe_dag_id }}')" aria-label="Delete DAG">
<span class="glyphicon glyphicon-trash text-danger" aria-hidden="true"></span>
</a>
</div>
</div>
</div>
</div>
<hr>
<!-- Modal -->
Expand All @@ -143,9 +126,9 @@ <h4 class="modal-title" id="myModalLabel">
<div class="modal-body">
<div id="div_btn_subdag">
<a id="btn_subdag" type="button" class="btn btn-primary" data-base-url="{{ url_for('Airflow.' + dag.default_view) }}">
Zoom into Sub DAG
</a>
<hr/>
Zoom into Sub DAG
</a>
<hr/>
</div>
<a id="btn_task" type="button" class="btn btn-primary" data-base-url="{{ url_for('Airflow.task') }}">
Task Instance Details
Expand All @@ -169,11 +152,11 @@ <h4 class="modal-title" id="myModalLabel">
</div>
<div id="dag_redir_logs">
{% if external_log_name is defined %}
<label style="display:inline"> View Logs in {{ external_log_name }} (by attempts): </label>
<ul class="nav nav-pills" role="tablist" id="redir_log_try_index" style="display:inline">
</ul>
<hr/>
<hr/>
<label style="display:inline"> View Logs in {{ external_log_name }} (by attempts): </label>
<ul class="nav nav-pills" role="tablist" id="redir_log_try_index" style="display:inline">
</ul>
<hr/>
<hr/>
{% endif %}
</div>
<form method="POST">
Expand Down Expand Up @@ -289,8 +272,7 @@ <h4 class="modal-title" id="myModalLabel">
</span>
</form>
<hr/>
<span class="btn-group" id="extra_links">
</span>
<span class="btn-group" id="extra_links"></span>
</div>

<div class="modal-footer">
Expand Down Expand Up @@ -345,16 +327,16 @@ <h4 class="modal-title" id="dagModalLabel">
{{ super() }}
<script src="{{ url_for_asset('bootstrap-toggle.min.js') }}"></script>
<script>
function updateQueryStringParameter(uri, key, value) {
var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");
var separator = uri.indexOf('?') !== -1 ? "&" : "?";
if (uri.match(re)) {
return uri.replace(re, '$1' + key + "=" + value + '$2');
}
else {
return uri + separator + key + "=" + value;
}
}
function updateQueryStringParameter(uri, key, value) {
var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");
var separator = uri.indexOf('?') !== -1 ? "&" : "?";
if (uri.match(re)) {
return uri.replace(re, '$1' + key + "=" + value + '$2');
}
else {
return uri + separator + key + "=" + value;
}
}

// Pills highlighting
$(document).ready(function () {
Expand Down Expand Up @@ -418,7 +400,6 @@ <h4 class="modal-title" id="dagModalLabel">
task_id: task_id,
execution_date: execution_date,
});

}

function call_modal(t, d, extra_links, try_numbers, sd) {
Expand Down Expand Up @@ -523,7 +504,6 @@ <h4 class="modal-title" id="dagModalLabel">
$('#extra_links').append(markupArr).show();
$('[data-toggle="tooltip"]').tooltip();
}

}

function call_modal_dag(dag) {
Expand Down Expand Up @@ -584,6 +564,5 @@ <h4 class="modal-title" id="dagModalLabel">
$buttons.addClass('btn-danger');
});
});

</script>
{% endblock %}
30 changes: 15 additions & 15 deletions airflow/www/templates/airflow/dags.html
Original file line number Diff line number Diff line change
Expand Up @@ -160,61 +160,61 @@ <h2>DAGs</h2>
<td class="text-center" style="display:flex;flex-direction:row;justify-content:space-around;">
{% if dag %}
<!-- Trigger Dag -->
<a href="{{ url_for('Airflow.trigger', dag_id=dag.dag_id) }}">
<span class="glyphicon glyphicon-play-circle" aria-hidden="true" data-original-title="Trigger Dag"></span>
<a href="{{ url_for('Airflow.trigger', dag_id=dag.dag_id) }}" aria-label="Trigger DAG">
<span class="glyphicon glyphicon-play" aria-hidden="true" data-original-title="Trigger DAG"></span>
</a>

<!-- Tree -->
<a href="{{ url_for('Airflow.tree', dag_id=dag.dag_id, num_runs=num_runs) }}">
<a href="{{ url_for('Airflow.tree', dag_id=dag.dag_id, num_runs=num_runs) }}" aria-label="Tree View">
<span class="glyphicon glyphicon-tree-deciduous" aria-hidden="true" data-original-title="Tree View"></span>
</a>

<!-- Graph -->
<a href="{{ url_for('Airflow.graph', dag_id=dag.dag_id) }}">
<a href="{{ url_for('Airflow.graph', dag_id=dag.dag_id) }}" aria-label="Graph View">
<span class="glyphicon glyphicon-certificate" aria-hidden="true" data-original-title="Graph View"></span>
</a>

<!-- Duration -->
<a href="{{ url_for('Airflow.duration', dag_id=dag.dag_id) }}">
<a href="{{ url_for('Airflow.duration', dag_id=dag.dag_id) }}" aria-label="Task Duration">
<span class="glyphicon glyphicon-stats" aria-hidden="true" data-original-title="Tasks Duration"></span>
</a>

<!-- Retries -->
<a href="{{ url_for('Airflow.tries', dag_id=dag.dag_id) }}">
<a href="{{ url_for('Airflow.tries', dag_id=dag.dag_id) }}" aria-label="Task Tries">
<span class="glyphicon glyphicon-duplicate" aria-hidden="true" data-original-title="Task Tries"></span>
</a>

<!-- Landing Times -->
<a href="{{ url_for("Airflow.landing_times", dag_id=dag.dag_id) }}">
<a href="{{ url_for('Airflow.landing_times', dag_id=dag.dag_id) }}" aria-label="Landing Times">
<span class="glyphicon glyphicon-plane" aria-hidden="true" data-original-title="Landing Times"></span>
</a>

<!-- Gantt -->
<a href="{{ url_for("Airflow.gantt", dag_id=dag.dag_id) }}">
<span class="glyphicon glyphicon-align-left" aria-hidden="true" data-original-title="Gantt View"></span>
<a href="{{ url_for('Airflow.gantt', dag_id=dag.dag_id) }}" aria-label="Gantt">
<span class="glyphicon glyphicon-align-left" aria-hidden="true" data-original-title="Gantt"></span>
</a>

<!-- Code -->
<a href="{{ url_for("Airflow.code", dag_id=dag.dag_id) }}">
<span class="glyphicon glyphicon-file" aria-hidden="true" data-original-title="Code View"></span>
<a href="{{ url_for('Airflow.code', dag_id=dag.dag_id) }}" aria-label="Code">
<span class="glyphicon glyphicon-file" aria-hidden="true" data-original-title="Code"></span>
</a>

<!-- Logs -->
<a href="{{ url_for('LogModelView.list') }}?_flt_3_dag_id={{ dag.dag_id }}&_od_LogModelView=desc&_oc_LogModelView=dttm">
<a href="{{ url_for('LogModelView.list') }}?_flt_3_dag_id={{ dag.dag_id }}&_od_LogModelView=desc&_oc_LogModelView=dttm" aria-label="Logs">
<span class="glyphicon glyphicon-align-justify" aria-hidden="true" data-original-title="Logs"></span>
</a>
{% endif %}

<!-- Refresh -->
<a href="{{ url_for("Airflow.refresh", dag_id=dag.dag_id) }}" onclick="postAsForm(this.href); return false">
<a href="{{ url_for('Airflow.refresh', dag_id=dag.dag_id) }}" onclick="postAsForm(this.href); return false" aria-label="Refresh DAG">
<span class="glyphicon glyphicon-refresh" aria-hidden="true" data-original-title="Refresh"></span>
</a>

<!-- Delete -->
<!-- Use dag_id instead of dag.dag_id, because the DAG might not exist in the webserver's DagBag -->
<a href="{{ url_for('Airflow.delete', dag_id=dag.dag_id) }}"
onclick="return confirmDeleteDag(this, '{{ dag.dag_id }}')">
<span class="glyphicon glyphicon-remove-circle" style="color:red" aria-hidden="true" data-original-title="Delete Dag"></span>
onclick="return confirmDeleteDag(this, '{{ dag.dag_id }}')" class="text-danger" aria-label="Delete DAG">
<span class="glyphicon glyphicon-trash" aria-hidden="true" data-original-title="Delete&nbsp;Dag"></span>
</a>
</td>
</tr>
Expand Down
Binary file modified docs/img/code.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/img/dags.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/img/duration.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/img/gantt.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/img/graph.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/img/tree.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 273e28c

Please sign in to comment.