{#


#}
{% 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 body %}
  <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="" title="Info">
                        <span class="glyphicon glyphicon-edit" aria-hidden="true"></span>
                    </a>
                    {% endif %}
                </td>

                <!-- Column 2: Turn dag on/off -->
                <td>

                </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('dagrun.index_view') }}?flt2_dag_id_equals={{ 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(include_externally_triggered=True) %}
                    {% 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 -->


                <!-- Tree -->
                <a href="{{ url_for('airflow.tree', dag_id=dag.dag_id, num_runs=num_runs) }}">
                    <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 -->


                <!-- Logs -->
                <a href="{{ url_for('log.index_view') }}?sort=1&amp;desc=1&amp;flt1_dag_id_equals={{ dag.dag_id }}">
                    <span class="glyphicon glyphicon-align-justify" aria-hidden="true" data-original-title="Logs"></span>
                </a>
                {% endif %}

                <!-- Refresh -->


                <!-- Delete -->


                </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('admin.index') }}?showPaused=False">Hide Paused DAGs</a>
    {% else %}
    <a href="{{ url_for('admin.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('admin.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("You didn't have the permission");
      }

      function confirmDeleteDag(dag_id){
          return confirm("You didn't have the permission");
      }
      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 = 'airflow/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");
      });

      $input.attr("autocomplete", "off");

      $('#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('dagrun.index_view') }}?flt1_dag_id_equals=" + d.dag_id + "&flt2_state_equals=" + 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', '270px')
              .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('taskinstance.index_view') }}?flt1_dag_id_equals=" + d.dag_id + "&flt2_state_equals=" + 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 %}
