airflow-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bo...@apache.org
Subject [04/14] incubator-airflow git commit: [AIRFLOW-1433][AIRFLOW-85] New Airflow Webserver UI with RBAC support
Date Fri, 23 Mar 2018 08:19:18 GMT
http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/05e1861e/airflow/www_rbac/static/pin.svg
----------------------------------------------------------------------
diff --git a/airflow/www_rbac/static/pin.svg b/airflow/www_rbac/static/pin.svg
new file mode 100644
index 0000000..f50fd39
--- /dev/null
+++ b/airflow/www_rbac/static/pin.svg
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg viewBox="-0.01 -0.01 1.01 1.01" version="1.1" xmlns="http://www.w3.org/2000/svg"  xmlns:xlink="http://www.w3.org/1999/xlink">
+    <defs>
+        <g id="WheelBack">
+            <path fill="inherit" d="
+                M 0.52 0.5
+                L 1 0.9
+                L 0.7 0.9
+                A 0.8 0.6 0 0 1 0.52 0.5
+                Z" />
+        </g>
+        <g id="WheelShadow">
+            <path fill="inherit" d="
+                M 0.52 0.5
+                A 0.8 0.6 0 0 0 0.7 0.9
+                C 0.63 0.9 0.58 0.88 0.52 0.85
+                A 2.5 1 0 0 1 0.5 0.5
+                Z" />
+        </g>
+        <g id="WheelFront">
+            <path fill="inherit" d="
+                M 0.5 0.5
+                A 2.5 1 0 0 0 0.52 0.85
+                L 0.28 0.65
+                C 0.29 0.55 0.44 0.48 0.5 0.5
+                Z" />
+        </g>
+        <g id="WheelOutline">
+            <path stroke="black" stroke-width="0.003" fill-opacity="0" d="
+                M 0.64 0.6
+                L 1 0.9
+                L 0.7 0.9
+                C 0.63 0.9 0.58 0.88 0.52 0.85
+                L 0.28 0.65
+                C 0.29 0.55 0.44 0.48 0.5 0.5
+                M 0.52 0.85
+                A 2.5 1 0 0 1 0.5 0.5
+                " />
+        </g>
+
+        <radialGradient id="GreenBack" cx="0" cy="1" r="1">
+            <stop offset="0%" stop-color="#00c813" />
+            <stop offset="100%" stop-color="#006f00" />
+        </radialGradient>
+        <radialGradient id="GreenShadow" cx="0" cy="1" r="1">
+            <stop offset="0%" stop-color="#008200" />
+            <stop offset="100%" stop-color="#007600" />
+        </radialGradient>
+        <radialGradient id="GreenFront" cx="0" cy="1" r="1">
+            <stop offset="0%" stop-color="#00cd1d" />
+            <stop offset="1000%" stop-color="#00ea50" />
+        </radialGradient>
+
+        <radialGradient id="PeriwinkleBack" cx="0" cy="1" r="1">
+            <stop offset="0%" stop-color="#56affe" />
+            <stop offset="100%" stop-color="#04a4ff" />
+        </radialGradient>
+        <radialGradient id="PeriwinkleShadow" cx="0" cy="1" r="1">
+            <stop offset="0%" stop-color="#3166d4" />
+            <stop offset="100%" stop-color="#1a519f" />
+        </radialGradient>
+        <radialGradient id="PeriwinkleFront" cx="0" cy="1" r="1">
+            <stop offset="0%" stop-color="#b1c8fd" />
+            <stop offset="100%" stop-color="#7fc4fe" />
+        </radialGradient>
+
+        <radialGradient id="RedBack" cx="0" cy="1" r="1">
+            <stop offset="0%" stop-color="#df2000" />
+            <stop offset="100%" stop-color="#570d00" />
+        </radialGradient>
+        <radialGradient id="RedShadow" cx="0" cy="1" r="1">
+            <stop offset="0%" stop-color="#8e1500" />
+            <stop offset="100%" stop-color="#4c0b00" />
+        </radialGradient>
+        <radialGradient id="RedFront" cx="0" cy="1" r="1">
+            <stop offset="0%" stop-color="#e12b00" />
+            <stop offset="100%" stop-color="#b62f00" />
+        </radialGradient>
+
+        <radialGradient id="AzureBack" cx="0" cy="1" r="1">
+            <stop offset="0%" stop-color="#00fffe" />
+            <stop offset="100%" stop-color="#00daff" />
+        </radialGradient>
+        <radialGradient id="AzureShadow" cx="0" cy="1" r="1">
+            <stop offset="0%" stop-color="#0091c5" />
+            <stop offset="100%" stop-color="#005e8d" />
+        </radialGradient>
+        <radialGradient id="AzureFront" cx="0" cy="1" r="1">
+            <stop offset="0%" stop-color="#00b6dd" />
+            <stop offset="100%" stop-color="#00ffff" />
+        </radialGradient>
+    </defs>
+
+    <use xlink:href="#WheelBack" fill="url(#GreenBack)" transform="rotate(0 0.5 0.5)" />
+    <use xlink:href="#WheelBack" fill="url(#PeriwinkleBack)" transform="rotate(90 0.5 0.5)" />
+    <use xlink:href="#WheelBack" fill="url(#RedBack)" transform="rotate(180 0.5 0.5)" />
+    <use xlink:href="#WheelBack" fill="url(#AzureBack)" transform="rotate(270 0.5 0.5)" />
+
+    <use xlink:href="#WheelShadow" fill="url(#GreenShadow)" transform="rotate(0 0.5 0.5)" />
+    <use xlink:href="#WheelShadow" fill="url(#PeriwinkleShadow)" transform="rotate(90 0.5 0.5)" />
+    <use xlink:href="#WheelShadow" fill="url(#RedShadow)" transform="rotate(180 0.5 0.5)" />
+    <use xlink:href="#WheelShadow" fill="url(#AzureShadow)" transform="rotate(270 0.5 0.5)" />
+
+    <use xlink:href="#WheelOutline" transform="rotate(0 0.5 0.5)" />
+    <use xlink:href="#WheelOutline" transform="rotate(90 0.5 0.5)" />
+    <use xlink:href="#WheelOutline" transform="rotate(180 0.5 0.5)" />
+    <use xlink:href="#WheelOutline" transform="rotate(270 0.5 0.5)" />
+
+    <use xlink:href="#WheelFront" fill="url(#GreenFront)" transform="rotate(0 0.5 0.5)" />
+    <use xlink:href="#WheelFront" fill="url(#PeriwinkleFront)" transform="rotate(90 0.5 0.5)" />
+    <use xlink:href="#WheelFront" fill="url(#RedFront)" transform="rotate(180 0.5 0.5)" />
+    <use xlink:href="#WheelFront" fill="url(#AzureFront)" transform="rotate(270 0.5 0.5)" />
+
+    <circle cx="0.5" cy="0.5" r="0.025" fill="black" />
+</svg>

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/05e1861e/airflow/www_rbac/static/pin_100.jpg
----------------------------------------------------------------------
diff --git a/airflow/www_rbac/static/pin_100.jpg b/airflow/www_rbac/static/pin_100.jpg
new file mode 100644
index 0000000..102f678
Binary files /dev/null and b/airflow/www_rbac/static/pin_100.jpg differ

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/05e1861e/airflow/www_rbac/static/pin_100.png
----------------------------------------------------------------------
diff --git a/airflow/www_rbac/static/pin_100.png b/airflow/www_rbac/static/pin_100.png
new file mode 100644
index 0000000..653e15b
Binary files /dev/null and b/airflow/www_rbac/static/pin_100.png differ

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/05e1861e/airflow/www_rbac/static/pin_25.png
----------------------------------------------------------------------
diff --git a/airflow/www_rbac/static/pin_25.png b/airflow/www_rbac/static/pin_25.png
new file mode 100644
index 0000000..ea6c3b9
Binary files /dev/null and b/airflow/www_rbac/static/pin_25.png differ

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/05e1861e/airflow/www_rbac/static/pin_30.png
----------------------------------------------------------------------
diff --git a/airflow/www_rbac/static/pin_30.png b/airflow/www_rbac/static/pin_30.png
new file mode 100644
index 0000000..582fbc6
Binary files /dev/null and b/airflow/www_rbac/static/pin_30.png differ

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/05e1861e/airflow/www_rbac/static/pin_35.png
----------------------------------------------------------------------
diff --git a/airflow/www_rbac/static/pin_35.png b/airflow/www_rbac/static/pin_35.png
new file mode 100644
index 0000000..956feca
Binary files /dev/null and b/airflow/www_rbac/static/pin_35.png differ

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/05e1861e/airflow/www_rbac/static/pin_40.png
----------------------------------------------------------------------
diff --git a/airflow/www_rbac/static/pin_40.png b/airflow/www_rbac/static/pin_40.png
new file mode 100644
index 0000000..f5f5a71
Binary files /dev/null and b/airflow/www_rbac/static/pin_40.png differ

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/05e1861e/airflow/www_rbac/static/pin_large.jpg
----------------------------------------------------------------------
diff --git a/airflow/www_rbac/static/pin_large.jpg b/airflow/www_rbac/static/pin_large.jpg
new file mode 100644
index 0000000..862e467
Binary files /dev/null and b/airflow/www_rbac/static/pin_large.jpg differ

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/05e1861e/airflow/www_rbac/static/pin_large.png
----------------------------------------------------------------------
diff --git a/airflow/www_rbac/static/pin_large.png b/airflow/www_rbac/static/pin_large.png
new file mode 100644
index 0000000..986c88b
Binary files /dev/null and b/airflow/www_rbac/static/pin_large.png differ

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/05e1861e/airflow/www_rbac/static/screenshots/gantt.png
----------------------------------------------------------------------
diff --git a/airflow/www_rbac/static/screenshots/gantt.png b/airflow/www_rbac/static/screenshots/gantt.png
new file mode 100644
index 0000000..2b21459
Binary files /dev/null and b/airflow/www_rbac/static/screenshots/gantt.png differ

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/05e1861e/airflow/www_rbac/static/screenshots/graph.png
----------------------------------------------------------------------
diff --git a/airflow/www_rbac/static/screenshots/graph.png b/airflow/www_rbac/static/screenshots/graph.png
new file mode 100644
index 0000000..f718356
Binary files /dev/null and b/airflow/www_rbac/static/screenshots/graph.png differ

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/05e1861e/airflow/www_rbac/static/screenshots/tree.png
----------------------------------------------------------------------
diff --git a/airflow/www_rbac/static/screenshots/tree.png b/airflow/www_rbac/static/screenshots/tree.png
new file mode 100644
index 0000000..78ae67a
Binary files /dev/null and b/airflow/www_rbac/static/screenshots/tree.png differ

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/05e1861e/airflow/www_rbac/static/sort_asc.png
----------------------------------------------------------------------
diff --git a/airflow/www_rbac/static/sort_asc.png b/airflow/www_rbac/static/sort_asc.png
new file mode 100644
index 0000000..e1ba61a
Binary files /dev/null and b/airflow/www_rbac/static/sort_asc.png differ

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/05e1861e/airflow/www_rbac/static/sort_both.png
----------------------------------------------------------------------
diff --git a/airflow/www_rbac/static/sort_both.png b/airflow/www_rbac/static/sort_both.png
new file mode 100644
index 0000000..af5bc7c
Binary files /dev/null and b/airflow/www_rbac/static/sort_both.png differ

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/05e1861e/airflow/www_rbac/static/sort_desc.png
----------------------------------------------------------------------
diff --git a/airflow/www_rbac/static/sort_desc.png b/airflow/www_rbac/static/sort_desc.png
new file mode 100644
index 0000000..0e156de
Binary files /dev/null and b/airflow/www_rbac/static/sort_desc.png differ

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/05e1861e/airflow/www_rbac/static/tree.css
----------------------------------------------------------------------
diff --git a/airflow/www_rbac/static/tree.css b/airflow/www_rbac/static/tree.css
new file mode 100644
index 0000000..9304bb1
--- /dev/null
+++ b/airflow/www_rbac/static/tree.css
@@ -0,0 +1,96 @@
+/**
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+#svg_container{
+   // overflow: scroll;
+}
+.node text {
+  font: 11px sans-serif;
+  pointer-events: none;
+}
+path.link {
+  fill: none;
+  stroke: #3182bd;
+  stroke-width: 1.5px;
+  opacity: 0.5;
+}
+g.tick line{
+  shape-rendering: crispEdges;
+}
+rect.state {
+    stroke: black;
+    shape-rendering: crispEdges;
+    cursor: pointer;
+}
+rect.null, rect.scheduled, rect.undefined {
+    fill: white;
+}
+rect.success {
+    fill: green;
+}
+rect.running {
+    fill: lime;
+}
+rect.failed {
+    fill: red;
+}
+rect.queued {
+    fill: gray;
+}
+rect.shutdown {
+    fill: blue;
+}
+rect.upstream_failed {
+    fill: orange;
+}
+rect.up_for_retry {
+    fill: gold;
+}
+rect.skipped {
+    fill: pink;
+}
+.tooltip.in {
+    opacity: 1;
+    filter: alpha(opacity=100);
+}
+
+.axis path, .axis line {
+    fill: none;
+    stroke: #000;
+}
+.axis text {
+    font: 11px sans-serif;
+}
+
+g.parent circle {
+    cursor: pointer;
+}
+
+g.node.collapsed circle {
+    stroke: #444;
+    stroke-width: 4px;
+}
+circle {
+    stroke: blue;
+    fill: white;
+    stroke-width: 1.5px;
+}
+g.axis path {
+    shape-rendering: crispEdges;
+}

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/05e1861e/airflow/www_rbac/templates/airflow/chart.html
----------------------------------------------------------------------
diff --git a/airflow/www_rbac/templates/airflow/chart.html b/airflow/www_rbac/templates/airflow/chart.html
new file mode 100644
index 0000000..983a8dc
--- /dev/null
+++ b/airflow/www_rbac/templates/airflow/chart.html
@@ -0,0 +1,57 @@
+{#
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+#}
+{% extends "airflow/dag.html" %}
+{% block title %}Airflow - DAGs{% endblock %}
+
+{% block head_css %}
+{{ super() }}
+<link rel="stylesheet" type="text/css"
+    href="{{ url_for('static', filename='tree.css') }}">
+<link rel="stylesheet" type="text/css"
+    href="{{ url_for('appbuilder.static',filename='datepicker/bootstrap-datepicker.css')}}" >
+<link rel="stylesheet" type="text/css"
+      href="{{ url_for("static", filename="dataTables.bootstrap.css") }}">
+<link rel="stylesheet" type="text/css"
+      href="{{ url_for("static", filename="nv.d3.css") }}">
+<script src="{{ url_for('static', filename='d3.v3.min.js') }}"></script>
+<script src="{{ url_for('static', filename='nv.d3.js') }}"></script>
+{% endblock %}
+
+{% block content %}
+{{ super() }}
+<div style="float: left" class="form-inline">
+    <form method="get" style="float:left;">
+        Base date: {{ form.base_date(class_="form-control") }}
+        Number of runs: {{ form.num_runs(class_="form-control") }}
+        <input type="hidden" name="root" value="{{ root if root else '' }}">
+        <input type="hidden" value="{{ dag.dag_id }}" name="dag_id">
+        <input type="submit" value="Go" class="btn btn-default"
+         action="" method="get">
+        <input name="_csrf_token" type="hidden" value="{{ csrf_token() }}">
+    </form>
+</div>
+<div style="clear: both;">{{ chart |safe }}</div>
+<hr/>
+{% endblock %}
+
+{% block tail %}
+    {{ super() }}
+    <div class="container"></div>
+
+    <script src="{{url_for('appbuilder.static',filename='datepicker/bootstrap-datepicker.js')}}"></script>
+{% endblock %}

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/05e1861e/airflow/www_rbac/templates/airflow/circles.html
----------------------------------------------------------------------
diff --git a/airflow/www_rbac/templates/airflow/circles.html b/airflow/www_rbac/templates/airflow/circles.html
new file mode 100644
index 0000000..027b4ff
--- /dev/null
+++ b/airflow/www_rbac/templates/airflow/circles.html
@@ -0,0 +1,144 @@
+{# 
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+  
+    http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+#}
+<div style="font-family: verdana;">
+    <h1>Airflow 404 = lots of circles</h1>
+    <div>{{ hostname }}</div>
+<div
+            id="div_svg"
+            class="content"
+            class="centered text-center"
+            style="border: 1px solid #CCC; padding:0px;margin:0;">
+        <svg></svg>
+
+    </div>
+    <script src="{{ url_for('static', filename='d3.v3.min.js') }}"></script>
+    <script>
+    var height =700;
+    var width = document.getElementById("div_svg").offsetWidth;
+    var points = 20;
+    var matrix = [];
+    var duration = 2000;
+    var i = 0;
+    var flip = 0;
+    var colors = [
+        "#FF5A5F", "#007A87", "#7B0051", "#00D1C1", "#8CE071", "#FFB400",
+        "#FFAA91", "#B4A76C", "#9CA299", "#565A5C"
+    ];
+
+
+    function choose(choices) {
+        var index = Math.floor(Math.random() * choices.length);
+        return choices[index];
+    }
+    // Making a matrix
+    for(var x=0; x<points; x++) {
+        for(var y=0; y<points; y++) {
+            matrix[i] = {
+                'x': x,
+                'y': y,
+            }
+            i += 1;
+        }
+    }
+    sclx = d3.scale.linear().domain([-1, points]).range([0, width]);
+    scly = d3.scale.linear().domain([-1, points]).range([0, height]);
+
+    circles = d3.select("svg")
+    .attr('width', "100%")
+
+    .attr('height', height)
+    .selectAll("circle").data(matrix).enter()
+    .append("circle")
+    .attr("stroke", 'black')
+    .attr("fill", 'none')
+    .attr("cx", function(d, i) {return sclx(d.x)})
+    .attr("cy", function(d, i) {return scly(d.y)})
+    .attr("r", function(d, i) {return 0});
+
+
+
+    function toggle(){
+        var size = 50 + (200* Math.random());
+        var y_delay = 0;
+        var random_delay = 0;
+        if(Math.random() > 0.7){
+            y_delay = 50+ (Math.random() * 50);
+        }
+        var x_delay = 0;
+        if(Math.random() > 0.7){
+            x_delay = 50+ (Math.random() * 50);
+        }
+        if(Math.random() > 0.7){
+            random_delay = 1;
+        }
+
+        var random_x = Math.random() * width;
+        var random_y = Math.random() * height;
+        if(Math.random() > 0.5){
+            col = choose(colors);
+        } else {
+            col = "black";
+        }
+        if(Math.random() > 0.8){
+            col = function() {return choose(colors)};
+        }
+
+
+
+        if (flip==0){
+
+            flip = 1;
+
+            circles.transition()
+            .duration(duration)
+            .attr("cx", function(d, i) {return sclx(d.x)})
+            .attr("cy", function(d, i) {return scly(d.y)})
+            .attr("stroke", col)
+            .delay(function(d, i) {return (random_delay * Math.random() * 1000) + (d.x*x_delay) + (d.y * y_delay)})
+            .attr("r", function(d, i) {return size});
+        }
+        else{
+            flip = 0;
+
+            if(Math.random() > 0.6){
+                circles.transition()
+                .duration(duration)
+                .attr("r", function(d, i) {return 0})
+                .attr("cx", function(d, i) {return random_x})
+                .attr("stroke", col)
+                .delay(function(d, i) {return (i/2) *  Math.random() * 5})
+                .attr("cy", function(d, i) {return random_y});
+            }
+            else{
+                circles.transition()
+                .duration(duration)
+                .attr("cx", function(d, i) {return sclx(d.x)})
+                .attr("cy", function(d, i) {return scly(d.y)})
+                .attr("stroke", col)
+                .delay(function(d, i) {return (random_delay * Math.random() * 1000) + (d.x*x_delay) + (d.y * y_delay)})
+                .attr("r", function(d, i) {return 0});
+            }
+        }
+
+    }
+
+    setInterval(toggle, duration*3);
+    toggle();
+
+    </script>
+

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/05e1861e/airflow/www_rbac/templates/airflow/code.html
----------------------------------------------------------------------
diff --git a/airflow/www_rbac/templates/airflow/code.html b/airflow/www_rbac/templates/airflow/code.html
new file mode 100644
index 0000000..de1c1d8
--- /dev/null
+++ b/airflow/www_rbac/templates/airflow/code.html
@@ -0,0 +1,43 @@
+{# 
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+  
+    http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+#}
+{% extends "airflow/master.html" %}
+
+{% block title %}
+    {{ title }}
+{% endblock %}
+
+{% block content %}
+    {{ super() }}
+    <h2>{{ title }}</h2>
+
+    {% if pre_subtitle %}
+        <pre>{{ pre_subtitle }}</pre>
+    {% endif %}
+
+    {% if subtitle %}
+        <h5>{{ subtitle }}</h5>
+    {% endif %}
+
+    {% if code %}
+        <pre>{{ code }}</pre>
+    {% endif %}
+
+    {% if code_html %}
+        {{ code_html|safe }}
+    {% endif %}
+{% endblock %}

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/05e1861e/airflow/www_rbac/templates/airflow/config.html
----------------------------------------------------------------------
diff --git a/airflow/www_rbac/templates/airflow/config.html b/airflow/www_rbac/templates/airflow/config.html
new file mode 100644
index 0000000..501ef66
--- /dev/null
+++ b/airflow/www_rbac/templates/airflow/config.html
@@ -0,0 +1,69 @@
+{#
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+#}
+{% extends "airflow/master.html" %}
+
+{% block title %}
+    {{ title }}
+{% endblock %}
+
+{% block content %}
+    {{ super() }}
+    <h2>{{ title }}</h2>
+
+    {% if pre_subtitle %}
+        <pre>{{ pre_subtitle }}</pre>
+    {% endif %}
+
+    {% if subtitle %}
+        <h5>{{ subtitle }}</h5>
+    {% endif %}
+
+    {% if code %}
+        <pre>{{ code }}</pre>
+    {% endif %}
+
+    {% if code_html %}
+        {{ code_html|safe }}
+    {% endif %}
+
+    <hr>
+
+    {% if table %}
+        <br>
+        <h3>Running Configuration</h3>
+        <br>
+        <div>
+            <table class="table table-striped table-bordered">
+                <tr>
+                    <th>Section</th>
+                    <th>Key</th>
+                    <th>Value</th>
+                    <th>Source</th>
+                </tr>
+                {% for section, key, value, source in table %}
+                    <tr>
+                        <td>{{ section }}</td>
+                        <td>{{ key }}</td>
+                        <td class='code'>{{ value }}</td>
+                        <td>{{ source }}</td>
+                    </tr>
+                {% endfor %}
+            </table>
+        </div>
+    {% endif %}
+{% endblock %}

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/05e1861e/airflow/www_rbac/templates/airflow/confirm.html
----------------------------------------------------------------------
diff --git a/airflow/www_rbac/templates/airflow/confirm.html b/airflow/www_rbac/templates/airflow/confirm.html
new file mode 100644
index 0000000..3d28035
--- /dev/null
+++ b/airflow/www_rbac/templates/airflow/confirm.html
@@ -0,0 +1,35 @@
+{# 
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+  
+    http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+#}
+{% extends "airflow/master.html" %}
+
+{% block content %}
+    {{ super() }}
+    <h2>Wait a minute.</h2>
+    <div class="panel">
+    <p>{{ message }}</p>
+    {% if details %}
+        <pre><code>{{ details }}</code></pre>
+    {% endif %}
+    </div>
+    <button class="btn btn-primary" onclick="window.location += '&confirmed=true'">
+        OK!
+    </button>
+    <button class="btn" onclick="window.history.back()">bail.</button>
+    <br>
+    <br>
+{% endblock %}

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/05e1861e/airflow/www_rbac/templates/airflow/conn_create.html
----------------------------------------------------------------------
diff --git a/airflow/www_rbac/templates/airflow/conn_create.html b/airflow/www_rbac/templates/airflow/conn_create.html
new file mode 100644
index 0000000..5e6326c
--- /dev/null
+++ b/airflow/www_rbac/templates/airflow/conn_create.html
@@ -0,0 +1,23 @@
+{# 
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+  
+    http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+#}
+{% extends 'appbuilder/general/model/add.html' %}
+
+{% block tail %}
+  {{ super() }}
+    <script src="{{ url_for('static', filename='connection_form.js') }}"></script>
+{% endblock %}

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/05e1861e/airflow/www_rbac/templates/airflow/conn_edit.html
----------------------------------------------------------------------
diff --git a/airflow/www_rbac/templates/airflow/conn_edit.html b/airflow/www_rbac/templates/airflow/conn_edit.html
new file mode 100644
index 0000000..2ff44be
--- /dev/null
+++ b/airflow/www_rbac/templates/airflow/conn_edit.html
@@ -0,0 +1,23 @@
+{# 
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+  
+    http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+#}
+{% extends 'appbuilder/general/model/edit.html' %}
+
+{% block tail %}
+  {{ super() }}
+    <script src="{{ url_for('static', filename='connection_form.js') }}"></script>
+{% endblock %}

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/05e1861e/airflow/www_rbac/templates/airflow/dag.html
----------------------------------------------------------------------
diff --git a/airflow/www_rbac/templates/airflow/dag.html b/airflow/www_rbac/templates/airflow/dag.html
new file mode 100644
index 0000000..02c2fdd
--- /dev/null
+++ b/airflow/www_rbac/templates/airflow/dag.html
@@ -0,0 +1,430 @@
+{#
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+#}
+{% extends "airflow/master.html" %}
+
+{% block title %}Airflow - DAG {{ dag.dag_id }}{% endblock %}
+
+{% block head_css %}
+  {{ super() }}
+  <link href="{{ url_for('static', filename='main.css') }}" rel="stylesheet">
+  <link href="{{ url_for('static', filename='bootstrap-toggle.min.css') }}" rel="stylesheet" type="text/css">
+{% endblock %}
+
+{% block content %}
+<div>
+    <h3 class="pull-left">
+      {% if dag.parent_dag %}
+        <span style='color:#AAA;'>SUBDAG: </span> <span> {{ dag.dag_id }}</span>
+      {% else %}
+        <input id="pause_resume" dag_id="{{ dag.dag_id }}" type="checkbox" {{ "checked" if not dag.is_paused else "" }} data-toggle="toggle" data-size="mini" method="post">
+        <span style='color:#AAA;'>DAG: </span> <span> {{ dag.dag_id }}</span> <small class="text-muted"> {{ dag.description }} </small>
+      {% endif %}
+      {% if root %}
+        <span style='color:#AAA;'>ROOT: </span> <span> {{ root }}</span>
+      {% endif %}
+    </h3>
+    <h4 class="pull-right">
+      <a class="label label-default" href="{{ url_for('DagRunModelView.list') }}?_flt_3_dag_id={{ dag.dag_id }}">
+        schedule: {{ dag.schedule_interval }}
+      </a>
+    </h4>
+  </div>
+  <div class="clearfix"></div>
+  <div>
+    <ul class="nav nav-pills">
+      {% if dag.parent_dag %}
+          <li class="never_active"><a href="{{ url_for("Airflow.graph", dag_id=dag.parent_dag.dag_id) }}">
+              <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) }}">
+          <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=25, root=root) }}">
+          <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) }}">
+          <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) }}">
+          <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) }}">
+          <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) }}">
+          <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.refresh", dag_id=dag.dag_id) }}" title="Refresh">
+          <span class="glyphicon glyphicon-refresh" aria-hidden="true"></span>
+          Refresh
+        </a>
+      </li>
+    </ul>
+  </div>
+  <hr>
+  <!-- Modal -->
+  <div class="modal fade" id="myModal"
+        tabindex="-1" role="dialog"
+      aria-labelledby="myModalLabel" aria-hidden="true">
+    <div class="modal-dialog">
+      <div class="modal-content">
+        <div class="modal-header">
+          <h4 class="modal-title" id="myModalLabel">
+            <span id='task_id'></span>
+            <button id="btn_filter" type="button" class="btn btn-default" title="Filter on this task and upstream ">
+              <span class="glyphicon glyphicon-filter" style="margin-left: 0px;" aria-hidden="true"></span>
+            </button>
+              on
+            <span id='execution_date'></span>
+          </h4>
+        </div>
+        <div class="modal-body">
+          <div id="div_btn_subdag">
+              <button id="btn_subdag" type="button" class="btn btn-primary">
+                Zoom into Sub DAG
+              </button>
+              <hr/>
+          </div>
+          <button id="btn_task" type="button" class="btn btn-primary">
+            Task Instance Details
+          </button>
+          <button id="btn_rendered" type="button" class="btn btn-primary">
+            Rendered
+          </button>
+          <button id="btn_ti" type="button" class="btn btn-primary">
+            Task Instances
+          </button>
+          <button id="btn_log" type="button" class="btn btn-primary">
+            View Log
+          </button>
+          <hr/>
+          <button id="btn_run" type="button" class="btn btn-primary"
+            title="Runs a single task instance">
+            Run
+          </button>
+          <span class="btn-group">
+            <button id="btn_ignore_all_deps"
+              type="button" class="btn" data-toggle="button"
+              title="Ignores all non-critical dependencies, including task state and task_deps"
+              >Ignore All Deps</button>
+          </span>
+          <span class="btn-group">
+            <button id="btn_ignore_ti_state"
+              type="button" class="btn" data-toggle="button"
+              title="Ignore previous success/failure"
+              >Ignore Task State</button>
+          </span>
+          <button id="btn_ignore_task_deps"
+            type="button" class="btn" data-toggle="button"
+            title="Disregard the task-specific dependencies, e.g. status of upstream task instances and depends_on_past"
+            >Ignore Task Deps</button>
+          </span>
+          <hr/>
+          <button id="btn_clear" type="button" class="btn btn-primary"
+              title="Clearing deletes the previous state of the task instance, allowing it to get re-triggered by the scheduler or a backfill command"
+              >Clear
+          </button>
+          <span class="btn-group">
+            <button id="btn_past"
+              type="button" class="btn" data-toggle="button"
+              title="Also include past task instances when clearing this one"
+              >Past</button>
+            <button id="btn_future"
+              type="button" class="btn" data-toggle="button"
+              title="Also include future task instances when clearing this one"
+              >Future</button>
+            <button id="btn_upstream"
+              type="button" class="btn" data-toggle="button"
+              title="Also include upstream dependencies"
+              >Upstream</button>
+            <button id="btn_downstream"
+              type="button" class="btn active" data-toggle="button"
+              title="Also include downstream dependencies"
+              >
+              Downstream
+            </button>
+            <button id="btn_recursive"
+              type="button" class="btn active" data-toggle="button">
+               Recursive
+            </button>
+          </span>
+          <hr/>
+          <button id="btn_success" type="button" class="btn btn-primary">
+            Mark Success
+          </button>
+          <span class="btn-group">
+            <button id="btn_success_past"
+              type="button" class="btn" data-toggle="button">Past</button>
+            <button id="btn_success_future"
+              type="button" class="btn" data-toggle="button">
+              Future
+            </button>
+            <button id="btn_success_upstream"
+              type="button" class="btn" data-toggle="button">Upstream</button>
+            <button id="btn_success_downstream"
+              type="button" class="btn" data-toggle="button">
+              Downstream
+            </button>
+          </span>
+        </div>
+        <div class="modal-footer">
+          <button type="button" class="btn btn-default" data-dismiss="modal">
+            Close
+          </button>
+        </div>
+      </div>
+    </div>
+  </div>
+  <!-- Modal for dag -->
+  <div class="modal fade" id="dagModal"
+        tabindex="-1" role="dialog"
+      aria-labelledby="dagModalLabel" aria-hidden="true">
+    <div class="modal-dialog">
+      <div class="modal-content">
+        <div class="modal-header">
+          <h4 class="modal-title" id="dagModalLabel">
+            <span id='dag_id'></span>
+          </h4>
+        </div>
+        <div class="modal-body">
+          <button id="btn_edit_dagrun" type="button" class="btn btn-primary">
+            Edit
+          </button>
+          <button id="btn_dagrun_clear" type="button" class="btn btn-primary">
+            Clear
+          </button>
+          <button id="btn_dagrun_success" type="button" class="btn btn-primary">
+            Mark Success
+          </button>
+        </div>
+        <div class="modal-footer">
+          <button type="button" class="btn btn-default" data-dismiss="modal">
+            Close
+          </button>
+        </div>
+      </div>
+    </div>
+  </div>
+{% endblock %}
+{% block tail %}
+  {{ super() }}
+  <script src="{{ url_for('static', filename='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;
+  }
+}
+
+    // Pills highlighting
+    $(document).ready(function () {
+      $('a[href*="' + this.location.pathname + '"]').parent().addClass('active');
+      $('.never_active').removeClass('active');
+    });
+
+    var id = '';
+    var dag_id = '{{ dag.dag_id }}';
+    var task_id = '';
+    var exection_date = '';
+    var subdag_id = '';
+    function call_modal(t, d, sd) {
+      task_id = t;
+      loc = String(window.location);
+      $("#btn_filter").on("click", function(){
+        window.location = updateQueryStringParameter(loc, "root", task_id);
+      });
+      subdag_id = sd;
+      execution_date = d;
+      $('#task_id').html(t);
+      $('#execution_date').html(d);
+      $('#myModal').modal({});
+      $("#myModal").css("margin-top","0px")
+        if (subdag_id===undefined)
+            $("#div_btn_subdag").hide();
+        else {
+            $("#div_btn_subdag").show();
+            subdag_id = "{{ dag.dag_id }}."+t;
+        }
+    }
+
+    function call_modal_dag(dag) {
+      id = dag && dag.id;
+      execution_date = dag && dag.execution_date;
+      $('#dag_id').html(dag_id);
+      $('#dagModal').modal({});
+      $("#dagModal").css("margin-top","0px");
+    }
+
+    $("#btn_rendered").click(function(){
+      url = "{{ url_for('Airflow.rendered') }}" +
+        "?task_id=" + encodeURIComponent(task_id) +
+        "&dag_id=" + encodeURIComponent(dag_id) +
+        "&execution_date=" + encodeURIComponent(execution_date);
+      window.location = url;
+    });
+
+    $("#btn_subdag").click(function(){
+      url = "{{ url_for('Airflow.graph') }}" +
+        "?dag_id=" + encodeURIComponent(subdag_id) +
+        "&execution_date=" + encodeURIComponent(execution_date);
+      window.location = url;
+    });
+
+    $("#btn_log").click(function(){
+      url = "{{ url_for('Airflow.log') }}" +
+        "?task_id=" + encodeURIComponent(task_id) +
+        "&dag_id=" + encodeURIComponent(dag_id) +
+        "&execution_date=" + encodeURIComponent(execution_date);
+      window.location = url;
+    });
+
+    $("#btn_task").click(function(){
+      url = "{{ url_for('Airflow.task') }}" +
+        "?task_id=" + encodeURIComponent(task_id) +
+        "&dag_id=" + encodeURIComponent(dag_id) +
+        "&execution_date=" + encodeURIComponent(execution_date);
+      window.location = url;
+    });
+
+    $("#btn_ti").click(function(){
+      url = "{{ url_for('TaskInstanceModelView.list') }}" +
+        "?flt1_dag_id_equals=" + dag_id +
+        "&_flt_3_task_id=" + task_id +
+        "&_oc_TaskInstanceModelView=execution_date";
+      window.location = url;
+    });
+
+    $("#btn_run").click(function(){
+      url = "{{ url_for('Airflow.run') }}" +
+        "?task_id=" + encodeURIComponent(task_id) +
+        "&dag_id=" + encodeURIComponent(dag_id) +
+        "&ignore_all_deps=" + $('#btn_ignore_all_deps').hasClass('active') +
+        "&ignore_task_deps=" + $('#btn_ignore_task_deps').hasClass('active') +
+        "&ignore_ti_state=" + $('#btn_ignore_ti_state').hasClass('active') +
+        "&execution_date=" + encodeURIComponent(execution_date) +
+        "&origin=" + encodeURIComponent(window.location);
+      window.location = url;
+    });
+
+    $("#btn_clear").click(function(){
+      url = "{{ url_for('Airflow.clear') }}" +
+        "?task_id=" + encodeURIComponent(task_id) +
+        "&dag_id=" + encodeURIComponent(dag_id) +
+        "&future=" + $('#btn_future').hasClass('active') +
+        "&past=" + $('#btn_past').hasClass('active') +
+        "&upstream=" + $('#btn_upstream').hasClass('active') +
+        "&downstream=" + $('#btn_downstream').hasClass('active') +
+        "&recursive=" + $('#btn_recursive').hasClass('active') +
+        "&execution_date=" + encodeURIComponent(execution_date) +
+        "&origin=" + encodeURIComponent(window.location);
+      window.location = url;
+    });
+
+    $("#btn_dagrun_clear").click(function(){
+      url = "{{ url_for('Airflow.dagrun_clear') }}" +
+        "?task_id=" + encodeURIComponent(task_id) +
+        "&dag_id=" + encodeURIComponent(dag_id) +
+        "&execution_date=" + encodeURIComponent(execution_date) +
+        "&origin=" + encodeURIComponent(window.location);
+      window.location = url;
+    });
+
+    $("#btn_success").click(function(){
+      url = "{{ url_for('Airflow.success') }}" +
+        "?task_id=" + encodeURIComponent(task_id) +
+        "&dag_id=" + encodeURIComponent(dag_id) +
+        "&upstream=" + $('#btn_success_upstream').hasClass('active') +
+        "&downstream=" + $('#btn_success_downstream').hasClass('active') +
+        "&future=" + $('#btn_success_future').hasClass('active') +
+        "&past=" + $('#btn_success_past').hasClass('active') +
+        "&execution_date=" + encodeURIComponent(execution_date) +
+        "&origin=" + encodeURIComponent(window.location);
+
+      window.location = url;
+    });
+
+    $('#btn_dagrun_success').click(function(){
+      url = "{{ url_for('Airflow.dagrun_success') }}" +
+        "?dag_id=" + encodeURIComponent(dag_id) +
+        "&execution_date=" + encodeURIComponent(execution_date) +
+        "&origin=" + encodeURIComponent(window.location);
+      window.location = url;
+    });
+
+    $("#btn_gantt").click(function(){
+      url = "{{ url_for('Airflow.gantt') }}" +
+        "?dag_id=" + encodeURIComponent(dag_id) +
+        "&execution_date=" + encodeURIComponent(execution_date);
+      window.location = url;
+    });
+
+    $("#btn_graph").click(function(){
+      url = "{{ url_for('Airflow.graph') }}" +
+        "?dag_id=" + encodeURIComponent(dag_id) +
+        "&execution_date=" + encodeURIComponent(execution_date);
+      window.location = url;
+    });
+
+    $("#pause_resume").change(function() {
+      var dag_id =  $(this).attr('dag_id');
+      if ($(this).prop('checked')) {
+        is_paused = 'true'
+      } else {
+        is_paused = 'false'
+      }
+      url = "{{ url_for('Airflow.paused') }}" + '?is_paused=' + is_paused + '&dag_id=' + encodeURIComponent(dag_id);
+      $.post(url);
+    });
+
+    $('#btn_edit_dagrun').click(function(){
+      window.location = "{{ url_for('DagModelView.show', pk=id) }}";
+
+    });
+
+  </script>
+{% endblock %}

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/05e1861e/airflow/www_rbac/templates/airflow/dag_code.html
----------------------------------------------------------------------
diff --git a/airflow/www_rbac/templates/airflow/dag_code.html b/airflow/www_rbac/templates/airflow/dag_code.html
new file mode 100644
index 0000000..dfab08b
--- /dev/null
+++ b/airflow/www_rbac/templates/airflow/dag_code.html
@@ -0,0 +1,58 @@
+{# 
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+  
+    http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+#}
+{% extends "airflow/dag.html" %}
+{% block title %}Airflow - DAGs{% endblock %}
+
+{% block content %}
+    {{ super() }}
+    <h4>{{ title }}</h4>
+    {% if html_code %}
+        {{ html_code|safe }}
+    {% endif %}
+    {% if code %}
+        <pre>{{ code }}</pre>
+    {% endif %}
+
+    {% if code_dict %}
+        {% for k, v in code_dict.items() %}
+            <h5>{{ k }}</h5>
+            <pre>{{ v }}</pre>
+        {% endfor %}
+    {% endif %}
+    {% if html_dict %}
+        {% for k, v in html_dict.items() %}
+            <h5>{{ k }}</h5>
+            {{ v|safe }}
+        {% endfor %}
+    {% endif %}
+{% endblock %}
+
+{% block tail %}
+    {{ super() }}
+    <script>
+      // We blur task_ids in demo mode
+    $( document ).ready(function() {
+      if ("{{ demo_mode }}" == "True") {
+          $("pre span.s").css({
+              'text-shadow': '0px 0px 10px red',
+              'color': 'transparent',
+          });
+      }
+    });
+    </script>
+{% endblock %}

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/05e1861e/airflow/www_rbac/templates/airflow/dag_details.html
----------------------------------------------------------------------
diff --git a/airflow/www_rbac/templates/airflow/dag_details.html b/airflow/www_rbac/templates/airflow/dag_details.html
new file mode 100644
index 0000000..dfd28bc
--- /dev/null
+++ b/airflow/www_rbac/templates/airflow/dag_details.html
@@ -0,0 +1,72 @@
+{# 
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+  
+    http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+#}
+{% extends "airflow/dag.html" %}
+
+{% block title %}
+    {{ title }}
+{% endblock %}
+
+{% block content %}
+    {{ super() }}
+    <h2>{{ title }}</h2>
+    <div>
+      {% for state, count in states %}
+      <a
+          class="btn"
+          style="border: none; background-color:{{ State.color(state)}}; color: {{ State.color_fg(state) }};"
+          href="/taskinstance/list/?_flt_3_dag_id={{ dag.dag_id }}&_flt_3_state={{ state }}">
+        {{ state }} <span class="badge">{{ count }}</span>
+      </a>
+      {% endfor %}
+    </div>
+    <br>
+    <table class="table table-striped table-bordered">
+      <tr>
+        <th>schedule_interval</td>
+        <td>{{ dag.schedule_interval }}</td>
+      </tr>
+      <tr>
+        <th>max_active_runs</td>
+        <td>{{ dag.active_runs | length }} / {{ dag.max_active_runs }}</td>
+      </tr>
+      <tr>
+        <th>concurrency</td>
+        <td>{{ dag.concurrency }}</td>
+      </tr>
+      <tr>
+        <th>default_args</td>
+        <td><code>{{ dag.default_args }}</code></td>
+      </tr>
+      <tr>
+        <th>tasks count</td>
+        <td>{{ dag.tasks|length }}</td>
+      </tr>
+      <tr>
+        <th>task ids</td>
+        <td>{{ dag.task_ids }}</td>
+      </tr>
+      <tr>
+        <th>filepath</td>
+        <td>{{ dag.filepath }}</td>
+      </tr>
+      <tr>
+        <th>owner</td>
+        <td>{{ dag.owner }}</td>
+      </tr>
+    </table >
+{% endblock %}

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/05e1861e/airflow/www_rbac/templates/airflow/dags.html
----------------------------------------------------------------------
diff --git a/airflow/www_rbac/templates/airflow/dags.html b/airflow/www_rbac/templates/airflow/dags.html
new file mode 100644
index 0000000..fc8418d
--- /dev/null
+++ b/airflow/www_rbac/templates/airflow/dags.html
@@ -0,0 +1,468 @@
+{#
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+#}
+{% extends "airflow/master.html" %}
+
+{% block title %}Airflow - DAGs{% endblock %}
+
+{% block head_css %}
+{{ super() }}
+<link href="{{ url_for("static", filename="dataTables.bootstrap.css") }}" rel="stylesheet" type="text/css" >
+<link href="{{ url_for("static", filename="bootstrap-toggle.min.css") }}" rel="stylesheet" type="text/css">
+{% endblock %}
+
+{% block content %}
+  <h2>DAGs</h2>
+
+  <div id="main_content" style="display:none;">
+    <div class="row">
+      <div class="col-sm-2">
+      </div>
+      <div class="col-sm-10">
+        <form id="search_form" class="form-inline" style="width: 100%; text-align: right;">
+            <div id="dags_filter" class="form-group" style="width: 100%;">
+              <label for="dag_query" style="width:20%; text-align: right;">Search:</label>
+              <input id="dag_query" type="text" class="typeahead form-control" data-provide="typeahead" style="width:50%;" value="{{search_query}}">
+            </div>
+        </form>
+      </div>
+    </div>
+    <table id="dags" class="table table-striped table-bordered">
+        <thead>
+            <tr>
+                <th></th>
+                <th width="12"><span id="pause_header" class="glyphicon glyphicon-info-sign" title="Use this toggle to pause a DAG. The scheduler won't schedule new tasks instances for a paused DAG. Tasks already running at pause time won't be affected."></span></th>
+                <th>DAG</th>
+                <th>Schedule</th>
+                <th>Owner</th>
+                <th style="padding-left: 5px;">Recent Tasks
+                  <span id="statuses_info" class="glyphicon glyphicon-info-sign" aria-hidden="true" title="Status of tasks from all active DAG runs or, if not currently active, from most recent run."></span>
+                  <img id="loading" width="15" src="{{ url_for("static", filename="loading.gif") }}">
+                </th>
+                <th style="padding-left: 5px;">Last Run <span id="statuses_info" class="glyphicon glyphicon-info-sign" aria-hidden="true" title="Execution Date/Time of Highest Dag Run."></span>
+                </th>
+                <th style="padding-left: 5px;">DAG Runs
+                  <span id="statuses_info" class="glyphicon glyphicon-info-sign" aria-hidden="true" title="Status of all previous DAG runs."></span>
+                  <img id="loading" width="15" src="{{ url_for("static", filename="loading.gif") }}">
+                </th>
+                <th class="text-center">Links</th>
+            </tr>
+        </thead>
+        <tbody>
+        {% for dag_id in dag_ids_in_page %}
+            {% set dag = webserver_dags[dag_id] if dag_id in webserver_dags else None %}
+            <tr>
+                <!-- Column 1: Edit dag -->
+                <td class="text-center" style="width:10px;">
+                    {% if dag_id in orm_dags %}
+                    <a href="{{ url_for('DagModelView.show', pk=dag_id) }}" title="Info">
+                        <span class="glyphicon glyphicon-edit" aria-hidden="true"></span>
+                    </a>
+                    {% endif %}
+                </td>
+
+                <!-- Column 2: Turn dag on/off -->
+                <td>
+                  {% if dag_id in orm_dags %}
+                    {% set disabled = 'disabled' if view_only else None %}
+                    <input id="toggle-{{ dag_id }}" {{ disabled }} dag_id="{{ dag_id }}" type="checkbox" {{ "checked" if not orm_dags[dag_id].is_paused else "" }} data-toggle="toggle" data-size="mini" method="post">
+                  {% endif %}
+                </td>
+
+                <!-- Column 3: Name -->
+                <td>
+                    {% if dag_id in webserver_dags %}
+                    <a href="{{ url_for('Airflow.'+dag.default_view, dag_id=dag.dag_id) }}" title="{{ dag.description }}">
+                        {{ dag_id }}
+                    </a>
+                    {% else %}
+                        {{ dag_id }}
+                        <span class="glyphicon glyphicon-info-sign" class="info" aria-hidden="true" title="This DAG isn't available in the web server's DagBag object. It shows up in this list because the scheduler marked it as active in the metadata database."></span>
+                    {% endif %}
+                    {% if dag_id not in orm_dags %}
+                        <span class="glyphicon glyphicon-info-sign" class="info" aria-hidden="true" title="This DAG seems to be existing only locally. The master scheduler doesn't seem to be aware of its existence."></span>
+                    {% endif %}
+                </td>
+
+                <!-- Column 4: Dag Schedule -->
+                <td>
+                    {% if dag_id in webserver_dags %}
+                    <a class="label label-default schedule {{ dag.dag_id }}" href="{{ url_for('DagRunModelView.list') }}?_flt_3_dag_id={{ dag.dag_id }}">
+                        {{ dag.schedule_interval }}
+                    </a>
+                    {% endif %}
+                </td>
+
+                <!-- Column 5: Dag Owners -->
+                <td>
+                  {{ dag.owner if dag else orm_dags[dag_id].owners }}
+                </td>
+
+                <!-- Column 6: Recent Tasks -->
+                <td style="padding:0px; width:200px; height:10px;">
+                    <svg height="10" width="10" id='task-run-{{ dag.safe_dag_id }}' style="display: block;"></svg>
+                </td>
+
+                <!-- Column 7: Last Run -->
+                <td class="text-nowrap latest_dag_run {{ dag.dag_id }}">
+                  {% if dag %}
+                    {% set last_run = dag.get_last_dagrun() %}
+                    {% if last_run and last_run.execution_date %}
+                      <a href="{{ url_for('Airflow.graph', dag_id=dag.dag_id, execution_date=last_run.execution_date) }}">
+                        {{ last_run.execution_date.strftime("%Y-%m-%d %H:%M") }}
+                      </a>
+                      <span aria-hidden="true" id="statuses_info" title="Start Date: {{ last_run.start_date.strftime("%Y-%m-%d %H:%M") }}" class="glyphicon glyphicon-info-sign"></span>
+                    {% endif %}
+                  {% endif %}
+                </td>
+
+                <!-- Column 8: Dag Runs -->
+                <td style="padding:0px; width:120px; height:10px;">
+                    <svg height="10" width="10" id='dag-run-{{ dag.safe_dag_id }}' style="display: block;"></svg>
+                </td>
+
+                <!-- Column 9: Links -->
+                <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) }}"
+                   onclick="return confirmTriggerDag('{{ dag.safe_dag_id }}')">
+                    <span class="glyphicon glyphicon-play-circle" aria-hidden="true" data-original-title="Trigger Dag"></span>
+                </a>
+
+                <!-- Tree -->
+                <a href="{{ url_for('Airflow.tree', dag_id=dag.dag_id, num_runs=25) }}">
+                    <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) }}">
+                    <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) }}">
+                    <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) }}">
+                    <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) }}">
+                    <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>
+
+                <!-- 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>
+
+                <!-- Logs -->
+                <a href="{{ url_for('LogModelView.list') }}?_flt_3_dag_id={{ dag.dag_id }}&_od_LogModelView=desc&_oc_LogModelView=dttm">
+                    <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_id) }}">
+                  <span class="glyphicon glyphicon-refresh" aria-hidden="true" data-original-title="Refresh"></span>
+                </a>
+
+                </td>
+            </tr>
+        {% endfor %}
+        </tbody>
+    </table>
+    <div class="row">
+      <div class="col-sm-12" style="text-align:right;">
+        <div class="dataTables_info" id="dags_info" role="status" aria-live="polite" style="padding-top: 0px;">Showing {{num_dag_from}} to {{num_dag_to}} of {{num_of_all_dags}} entries</div>
+      </div>
+    </div>
+    <div class="row">
+      <div class="col-sm-12" style="text-align:left;">
+        <div class="dataTables_info" id="dags_paginate">
+          {{paging}}
+        </div>
+      </div>
+
+    </div>
+    {% if not hide_paused %}
+    <a href="{{ url_for('Airflow.index') }}?showPaused=False">Hide Paused DAGs</a>
+    {% else %}
+    <a href="{{ url_for('Airflow.index') }}?showPaused=True">Show Paused DAGs</a>
+    {% endif %}
+  </div>
+{% endblock %}
+
+{% block tail %}
+  {{ super() }}
+  <script src="{{ url_for('static', filename='d3.v3.min.js') }}"></script>
+  <script src="{{ url_for('static', filename='jquery.dataTables.min.js') }}"></script>
+  <script src="{{ url_for('static', filename='bootstrap-toggle.min.js') }}"></script>
+  <script src="{{ url_for('static', filename='bootstrap3-typeahead.min.js') }}"></script>
+  <script>
+
+      const DAGS_INDEX = "{{ url_for('Airflow.index') }}"
+      const ENTER_KEY_CODE = 13
+
+      $('#dag_query').on('keypress', function (e) {
+        // check for key press on ENTER (key code 13) to trigger the search
+        if (e.which === ENTER_KEY_CODE) {
+          search_query = $('#dag_query').val();
+          window.location = DAGS_INDEX + "?search="+ encodeURI(search_query);
+          e.preventDefault();
+        }
+      });
+
+      $('#page_size').on('change', function() {
+        p_size = $(this).val();
+        window.location = DAGS_INDEX + "?page_size=" + p_size;
+      });
+
+      function confirmTriggerDag(dag_id){
+          return confirm("Are you sure you want to run '"+dag_id+"' now?");
+      }
+      all_dags = $("[id^=toggle]");
+      $.each(all_dags, function(i,v) {
+        $(v).change (function() {
+          var dag_id =  $(v).attr('dag_id');
+          if ($(v).prop('checked')) {
+            is_paused = 'true'
+          } else {
+            is_paused = 'false'
+          }
+          url = 'paused?is_paused=' + is_paused + '&dag_id=' + dag_id;
+          $.post(url);
+        });
+      });
+
+      var $input = $(".typeahead");
+      unique_options_search = new Set([
+          {% for token in auto_complete_data %}
+            "{{token}}",
+          {% endfor %}
+        ]);
+
+      $input.typeahead({
+        source: [...unique_options_search],
+        autoSelect: false,
+        afterSelect: function(value) {
+          search_query = value.trim()
+          if (search_query) {
+            window.location = DAGS_INDEX + "?search="+ encodeURI(search_query);
+          }
+        }
+      });
+
+      $input.change(function() {
+        var current = $input.typeahead("getActive");
+
+      });
+
+      $('#dags').dataTable({
+        "iDisplayLength": 500,
+        "bSort": false,
+        "searching": false,
+        "ordering": false,
+        "paging": false,
+        "info": false
+      });
+      $("#main_content").show(250);
+      diameter = 25;
+      circle_margin = 4;
+      stroke_width = 2;
+      stroke_width_hover = 6;
+      d3.json("{{ url_for('Airflow.blocked') }}", function(error, json) {
+        $.each(json, function() {
+          $('.label.schedule.' + this.dag_id)
+          .attr('title', this.active_dag_run + '/' + this.max_active_runs + ' active dag runs')
+          .tooltip();
+          if(this.active_dag_run >= this.max_active_runs) {
+            $('.label.schedule.' + this.dag_id)
+            .css('background-color', 'red');
+          }
+        });
+      });
+      d3.json("{{ url_for('Airflow.dag_stats') }}", function(error, json) {
+        for(var dag_id in json) {
+            states = json[dag_id];
+            g = d3.select('svg#dag-run-' + dag_id)
+              .attr('height', diameter + (stroke_width_hover * 2))
+              .attr('width', '110px')
+              .selectAll("g")
+              .data(states)
+              .enter()
+              .append('g')
+              .attr('transform', function(d, i) {
+                x = (i * (diameter + circle_margin)) + (diameter/2 + circle_margin);
+                y = (diameter/2) + stroke_width_hover;
+                return 'translate(' + x + ',' + y + ')';
+              });
+
+            g.append('text')
+              .attr('fill', 'black')
+              .attr('text-anchor', 'middle')
+              .attr('vertical-align', 'middle')
+              .attr('font-size', 8)
+              .attr('y', 3)
+              .text(function(d){ return d.count > 0 ? d.count : ''; });
+
+            g.append('circle')
+              .attr('stroke-width', function(d) {
+                  if (d.count > 0)
+                    return stroke_width;
+                  else {
+                    return 1;
+                  }
+              })
+              .attr('stroke', function(d) {
+                  if (d.count > 0)
+                    return d.color;
+                  else {
+                    return 'gainsboro';
+                  }
+              })
+              .attr('fill-opacity', 0)
+              .attr('r', diameter/2)
+              .attr('title', function(d) {return d.state})
+              .attr('style', function(d) {
+                if (d.count > 0)
+                    return"cursor:pointer;"
+              })
+              .on('click', function(d, i) {
+                  if (d.count > 0)
+                    window.location = "{{ url_for('DagRunModelView.list') }}?_flt_3_dag_id=" + d.dag_id + "&_flt_3_state=" + d.state;
+              })
+              .on('mouseover', function(d, i) {
+                if (d.count > 0) {
+                    d3.select(this).transition().duration(400)
+                      .attr('fill-opacity', 0.3)
+                      .style("stroke-width", stroke_width_hover);
+                }
+              })
+              .on('mouseout', function(d, i) {
+                if (d.count > 0) {
+                    d3.select(this).transition().duration(400)
+                      .attr('fill-opacity', 0)
+                      .style("stroke-width", stroke_width);
+                }
+              })
+              .style("opacity", 0)
+              .transition()
+              .duration(500)
+              .delay(function(d, i){return i*50;})
+              .style("opacity", 1);
+            d3.select("#loading").remove();
+        }
+        $("#pause_header").tooltip();
+        $("#statuses_info").tooltip();
+
+        $("circle").tooltip({
+          html: true,
+          container: "body",
+        });
+      });
+      d3.json("{{ url_for('Airflow.task_stats') }}", function(error, json) {
+        for(var dag_id in json) {
+            states = json[dag_id];
+            g = d3.select('svg#task-run-' + dag_id)
+              .attr('height', diameter + (stroke_width_hover * 2))
+              .attr('width', '240px')
+              .selectAll("g")
+              .data(states)
+              .enter()
+              .append('g')
+              .attr('transform', function(d, i) {
+                x = (i * (diameter + circle_margin)) + (diameter/2 + circle_margin);
+                y = (diameter/2) + stroke_width_hover;
+                return 'translate(' + x + ',' + y + ')';
+              });
+
+            g.append('text')
+              .attr('fill', 'black')
+              .attr('text-anchor', 'middle')
+              .attr('vertical-align', 'middle')
+              .attr('font-size', 8)
+              .attr('y', 3)
+              .text(function(d){ return d.count > 0 ? d.count : ''; });
+
+            g.append('circle')
+              .attr('stroke-width', function(d) {
+                  if (d.count > 0)
+                    return stroke_width;
+                  else {
+                    return 1;
+                  }
+              })
+              .attr('stroke', function(d) {
+                  if (d.count > 0)
+                    return d.color;
+                  else {
+                    return 'gainsboro';
+                  }
+              })
+              .attr('fill-opacity', 0)
+              .attr('r', diameter/2)
+              .attr('title', function(d) {return d.state})
+              .attr('style', function(d) {
+                if (d.count > 0)
+                    return"cursor:pointer;"
+              })
+              .on('click', function(d, i) {
+                  if (d.count > 0)
+                    window.location = "{{ url_for('TaskInstanceModelView.list') }}?_flt_3_dag_id=" + d.dag_id + "&_flt_3_state=" + d.state;
+              })
+              .on('mouseover', function(d, i) {
+                if (d.count > 0) {
+                    d3.select(this).transition().duration(400)
+                      .attr('fill-opacity', 0.3)
+                      .style("stroke-width", stroke_width_hover);
+                }
+              })
+              .on('mouseout', function(d, i) {
+                if (d.count > 0) {
+                    d3.select(this).transition().duration(400)
+                      .attr('fill-opacity', 0)
+                      .style("stroke-width", stroke_width);
+                }
+              })
+              .style("opacity", 0)
+              .transition()
+              .duration(500)
+              .delay(function(d, i){return i*50;})
+              .style("opacity", 1);
+            d3.select("#loading").remove();
+        }
+        $("#pause_header").tooltip();
+        $("#statuses_info").tooltip();
+
+        $("circle").tooltip({
+          html: true,
+          container: "body",
+        });
+      });
+  </script>
+{% endblock %}

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/05e1861e/airflow/www_rbac/templates/airflow/duration_chart.html
----------------------------------------------------------------------
diff --git a/airflow/www_rbac/templates/airflow/duration_chart.html b/airflow/www_rbac/templates/airflow/duration_chart.html
new file mode 100644
index 0000000..89ddb94
--- /dev/null
+++ b/airflow/www_rbac/templates/airflow/duration_chart.html
@@ -0,0 +1,77 @@
+{#
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+#}
+{% extends "airflow/dag.html" %}
+{% block title %}Airflow - DAGs{% endblock %}
+
+{% block head_css %}
+{{ super() }}
+<link rel="stylesheet" type="text/css"
+    href="{{ url_for('static', filename='tree.css') }}">
+<link rel="stylesheet" type="text/css"
+    href="{{url_for('appbuilder.static',filename='datepicker/bootstrap-datepicker.css')}}" >
+<link rel="stylesheet" type="text/css"
+      href="{{ url_for("static", filename="dataTables.bootstrap.css") }}">
+<link rel="stylesheet" type="text/css"
+      href="{{ url_for("static", filename="nv.d3.css") }}">
+<script src="{{ url_for('static', filename='d3.v3.min.js') }}"></script>
+<script src="{{ url_for('static', filename='nv.d3.js') }}"></script>
+{% endblock %}
+
+{% block content %}
+{{ super() }}
+<div>
+  <label for="isCumulative">Cumulative Duration</label>
+  <input id="isCumulative" type="checkbox" value="1">
+</div>
+<div style="float: left" class="form-inline">
+    <form method="get" style="float:left;">
+        Base date: {{ form.base_date(class_="form-control") }}
+        Number of runs: {{ form.num_runs(class_="form-control") }}
+        <input type="hidden" name="root" value="{{ root if root else '' }}">
+        <input type="hidden" value="{{ dag.dag_id }}" name="dag_id">
+        <input type="submit" value="Go" class="btn btn-default"
+         action="" method="get">
+        <input name="_csrf_token" type="hidden" value="{{ csrf_token() }}">
+    </form>
+</div>
+<div id="dur_chart" style="clear: both;">{{ chart |safe }}</div>
+<div id="cum_dur_chart" style="clear: both;">{{ cum_chart | safe}}</div>
+<hr/>
+{% endblock %}
+
+{% block tail %}
+  <script>
+    function handleCheck() {
+      if ($('#isCumulative').is(':checked')) {
+        $('#dur_chart').hide();
+        $('#cum_dur_chart').show();
+      } else {
+        $('#dur_chart').show();
+        $('#cum_dur_chart').hide();
+      };
+    };
+    $( document ).on('chartload', function() {
+      handleCheck();
+    });
+    $('#isCumulative').click(function() {
+      handleCheck();
+    });
+  </script>
+  <script src="{{url_for('appbuilder.static',filename='datepicker/bootstrap-datepicker.js')}}"></script>
+  {{ super() }}
+{% endblock %}

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/05e1861e/airflow/www_rbac/templates/airflow/gantt.html
----------------------------------------------------------------------
diff --git a/airflow/www_rbac/templates/airflow/gantt.html b/airflow/www_rbac/templates/airflow/gantt.html
new file mode 100644
index 0000000..3cdb269
--- /dev/null
+++ b/airflow/www_rbac/templates/airflow/gantt.html
@@ -0,0 +1,67 @@
+{#
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+#}
+{% extends "airflow/dag.html" %}
+
+{% block head_css %}
+{{ super() }}
+<link rel="stylesheet" type="text/css"
+    href="{{url_for('appbuilder.static',filename='datepicker/bootstrap-datepicker.css')}}" >
+<link type="text/css" href="{{ url_for('static', filename='gantt.css') }}" rel="stylesheet" />
+<link type="text/css" href="{{ url_for('static', filename='tree.css') }}" rel="stylesheet" />
+{% endblock %}
+
+{% block content %}
+{{ super() }}
+<form method="get">
+  <div class="form-inline">
+    Run:<input type="hidden" value="{{ dag.dag_id }}" name="dag_id">
+    {{ form.execution_date(class_="form-control") | safe }}
+    <input type="submit" value="Go" class="btn btn-default" action="" method="get">
+    <input type="hidden" name="root" value="{{ root if root else '' }}">
+    <input name="_csrf_token" type="hidden" value="{{ csrf_token() }}">
+  </div>
+</form>
+<div style="clear: both;"></div>
+<div class="container">
+  <div class="gantt"></div>
+</div>
+{% endblock %}
+
+{% block tail %}
+{{ super() }}
+<script src="{{ url_for('appbuilder.static',filename='datepicker/bootstrap-datepicker.js') }}"></script>
+<script src="{{ url_for('static', filename='d3.v3.min.js') }}"></script>
+<script src="{{ url_for('static', filename='d3.tip.v0.6.3.js') }}"></script>/
+<script src="{{ url_for('static', filename='gantt-chart-d3v2.js') }}"></script>
+<script>
+  $( document ).ready(function() {
+    var dag_id = '{{ dag.dag_id }}';
+    var task_id = '';
+    var exection_date = '';
+    data = {{ data |safe }};
+    var gantt = d3.gantt()
+      .taskTypes(data.taskNames)
+      .taskStatus(data.taskStatus)
+      .height(data.height)
+      .selector('.gantt')
+      .tickFormat("%H:%M:%S");
+    gantt(data.tasks);
+  });
+</script>
+
+{% endblock %}


Mime
View raw message