Explorar o código

HUE-2751 [oozie] Paginate Coordinator dashboard tables

krish %!s(int64=10) %!d(string=hai) anos
pai
achega
fb12f43bb1

+ 0 - 1
apps/oozie/src/oozie/static/oozie/js/dashboard-utils.js

@@ -46,7 +46,6 @@ function emptyStringIfNull(obj) {
 }
 
 var PersistedButtonsFilters = function (oSettings, aData, iDataIndex) {
-  var urlHashes = "";
 
   var submittedBtn = $("a.btn-submitted.active");
   var submittedByFilter = true;

+ 158 - 36
apps/oozie/src/oozie/templates/dashboard/list_oozie_coordinators.mako

@@ -29,7 +29,7 @@ ${layout.menubar(section='coordinators', dashboard=True)}
 
 <div class="container-fluid">
   <div class="card card-small">
-  <div class="card-body">
+  <div class="card-body" style="padding-bottom: 20px">
   <p>
   <form>
     <input type="text" id="filterInput" class="input-xlarge search-query" placeholder="${ _('Search for username, name, etc...') }">
@@ -55,7 +55,7 @@ ${layout.menubar(section='coordinators', dashboard=True)}
       <span class="btn-group" style="float:left;">
         <a class="btn btn-status btn-success" data-value='SUCCEEDED'>${ _('Succeeded') }</a>
         <a class="btn btn-status btn-warning" data-value='RUNNING'>${ _('Running') }</a>
-        <a class="btn btn-status btn-danger disable-feedback" data-value='KILLED'>${ _('Killed') }</a>
+        <a class="btn btn-status btn-danger disable-feedback" data-value='ERROR'>${ _('Error') }</a>
       </span>
     </span>
   </form>
@@ -98,6 +98,16 @@ ${layout.menubar(section='coordinators', dashboard=True)}
         </tr>
       </tbody>
     </table>
+
+    <span class="running-info" style="padding-left: 4px"></span>
+
+    <div class="pagination dataTables_paginate">
+      <ul>
+        <li class="prev"><a href="javascript:void(0)" class="btn-pagination" data-value="prev" data-table="running"><i class="fa fa-long-arrow-left"></i> ${ _('Previous') }</a></li>
+        <li class="next"><a href="javascript:void(0)" class="btn-pagination" data-value="next" data-table="running">${ _('Next') } <i class="fa fa-long-arrow-right"></i></a></li>
+      </ul>
+    </div>
+
   </div>
 
   <div>
@@ -136,6 +146,16 @@ ${layout.menubar(section='coordinators', dashboard=True)}
         </tr>
       </tbody>
      </table>
+
+     <span class="completed-info" style="padding-left: 4px"></span>
+
+     <div class="pagination dataTables_paginate">
+      <ul>
+        <li class="prev"><a href="javascript:void(0)" class="btn-pagination" data-value="prev" data-table="completed"><i class="fa fa-long-arrow-left"></i> ${ _('Previous') }</a></li>
+        <li class="next"><a href="javascript:void(0)" class="btn-pagination" data-value="next" data-table="completed">${ _('Next') } <i class="fa fa-long-arrow-right"></i></a></li>
+      </ul>
+     </div>
+
    </div>
   </p>
   </div>
@@ -189,13 +209,33 @@ ${layout.menubar(section='coordinators', dashboard=True)}
   }
 
   var refreshRunning;
+  var runningTableOffset = 1, completedTableOffset = 1;
+  var totalRunningJobs = 0, totalCompletedJobs = 0;
+  var PAGE_SIZE = 50;
 
   $(document).ready(function () {
+
+    function showTableInfo(oSettings, table, tableOffset, totalJobs) {
+      var _disp = oSettings.fnRecordsDisplay();
+      var _tot = oSettings.fnRecordsTotal();
+      var _text = "";
+      if (_disp == 0) {
+        _text = '${_("Showing 0 to 0 of ")}' + totalJobs + '${_(" entries")}';
+      }
+      else {
+        _text = ' ${_("Showing ")}' + tableOffset + '${_(" to ")}' + (tableOffset + oSettings.fnDisplayEnd() - 1) + '${_(" of ")}' + totalJobs;
+      }
+      if (_disp != _tot) { // when filter button is selected
+          _text += '${_(" (filtered from ")}' + _tot + '${_(" entries)")}';
+      }
+      $(table).text(_text);
+    }
+
     var runningTable = $("#running-table").dataTable({
-      "sPaginationType":"bootstrap",
-      "iDisplayLength":50,
+      "bPaginate": false,
+      "iDisplayLength":PAGE_SIZE,
       "bLengthChange":false,
-      "sDom":"<'row'r>t<'row'<'span6'i><''p>>",
+      "sDom":"<'row'r>t<'row'<'span6'><''p>>",
       "aoColumns":[
         { "bSortable":false },
         { "sSortDataType":"dom-sort-value", "sType":"numeric" },
@@ -214,28 +254,19 @@ ${layout.menubar(section='coordinators', dashboard=True)}
         [ 0, "desc" ]
       ],
       "oLanguage":{
-        "sEmptyTable":"${_('No data available')}",
-        "sInfo":"${_('Showing _START_ to _END_ of _TOTAL_ entries')}",
-        "sInfoEmpty":"${_('Showing 0 to 0 of 0 entries')}",
-        "sInfoFiltered":"${_('(filtered from _MAX_ total entries)')}",
-        "sZeroRecords":"${_('No matching records')}",
-        "oPaginate":{
-          "sFirst":"${_('First')}",
-          "sLast":"${_('Last')}",
-          "sNext":"${_('Next')}",
-          "sPrevious":"${_('Previous')}"
-        }
+        "sZeroRecords":"${_('No matching records')}"
       },
       "fnDrawCallback":function (oSettings) {
+        showTableInfo(oSettings, ".running-info", runningTableOffset, totalRunningJobs);
         $("a[data-row-selector='true']").jHueRowSelector();
       }
     });
 
     var completedTable = $("#completed-table").dataTable({
-      "sPaginationType":"bootstrap",
-      "iDisplayLength":50,
+      "bPaginate": false,
+      "iDisplayLength":PAGE_SIZE,
       "bLengthChange":false,
-      "sDom":"<'row'r>t<'row'<'span6'i><''p>>",
+      "sDom":"<'row'r>t<'row'<'span6'><''p>>",
       "aoColumns":[
         { "sSortDataType":"dom-sort-value", "sType":"numeric" },
         null,
@@ -253,19 +284,10 @@ ${layout.menubar(section='coordinators', dashboard=True)}
         [ 0, "desc" ]
       ],
       "oLanguage":{
-        "sEmptyTable":"${_('No data available')}",
-        "sInfo":"${_('Showing _START_ to _END_ of _TOTAL_ entries')}",
-        "sInfoEmpty":"${_('Showing 0 to 0 of 0 entries')}",
-        "sInfoFiltered":"${_('(filtered from _MAX_ total entries)')}",
-        "sZeroRecords":"${_('No matching records')}",
-        "oPaginate":{
-          "sFirst":"${_('First')}",
-          "sLast":"${_('Last')}",
-          "sNext":"${_('Next')}",
-          "sPrevious":"${_('Previous')}"
-        }
+        "sZeroRecords":"${_('No matching records')}"
       },
       "fnDrawCallback":function (oSettings) {
+        showTableInfo(oSettings, ".completed-info", completedTableOffset, totalCompletedJobs);
         $("a[data-row-selector='true']").jHueRowSelector();
       }
     });
@@ -288,13 +310,35 @@ ${layout.menubar(section='coordinators', dashboard=True)}
       window.location.hash = hash;
     });
 
+    $("a.btn-pagination").on("click", function () {
+      if (!$(this).parent().hasClass("disabled")) {
+        var _additionalOffset = 0;
+        if ($(this).data("value") == "prev") {
+          _additionalOffset = -PAGE_SIZE;
+        }
+        else {
+          _additionalOffset = PAGE_SIZE;
+        }
+        if ($(this).data("table") == "running") {
+          runningTableOffset += _additionalOffset;
+          refreshRunning();
+        }
+        else {
+          completedTableOffset += _additionalOffset;
+          refreshCompleted();
+        }
+      }
+    });
 
     $("a.btn-status").click(function () {
+      refreshPagination();
       $(this).toggleClass("active");
-      drawTable();
+      refreshRunning();
+      refreshCompleted();
     });
 
     $("a.btn-date").click(function () {
+      refreshPagination();
       $("a.btn-date").not(this).removeClass("active");
       $(this).toggleClass("active");
       drawTable();
@@ -305,6 +349,11 @@ ${layout.menubar(section='coordinators', dashboard=True)}
       $("a.btn-date[data-value='" + hash.split("=")[1] + "']").click();
     }
 
+    function refreshPagination() {
+      runningTableOffset = 1;
+      completedTableOffset = 1;
+    }
+
     function drawTable() {
       runningTable.fnDraw();
       completedTable.fnDraw();
@@ -316,9 +365,49 @@ ${layout.menubar(section='coordinators', dashboard=True)}
       window.location.hash = hash;
     }
 
+    function getStatuses(type) {
+      var selectedStatuses = (type == 'running') ? ['RUNNING', 'PREP', 'SUSPENDED'] : ['SUCCEEDED', 'KILLED', 'FAILED'];
+      var btnStatuses = [];
+
+      var statusBtns = $("a.btn-status.active");
+      $.each(statusBtns, function () {
+        val = $(this).data('value');
+        if (val == 'SUCCEEDED') {
+          btnStatuses = btnStatuses.concat(['SUCCEEDED']);
+        } else if (val == 'RUNNING') {
+          btnStatuses = btnStatuses.concat(['RUNNING', 'PREP', 'SUSPENDED']);
+        } else if (val == 'ERROR') {
+          btnStatuses = btnStatuses.concat(['KILLED', 'FAILED']);
+        }
+      });
+
+      if (btnStatuses.length > 0) {
+        selectedStatuses = $.makeArray($(selectedStatuses).filter(btnStatuses));
+      }
+
+      return selectedStatuses.length > 0 ? ('&status=' + selectedStatuses.join('&status=')) : '';
+    }
+
+    var CoordinatorButtonsFilters = function (oSettings, aData, iDataIndex) {
+      var dateBtn = $("a.btn-date.active");
+      var dateFilter = true;
+      if (dateBtn.length > 0) {
+        var minAge = new Date() - parseInt(dateBtn.attr("data-value")) * 1000 * 60 * 60 * 24;
+        var _dateColumn = aData[1];
+        if (typeof $(_dateColumn).attr("data-type") == "undefined" || $(_dateColumn).attr("data-type") == "status") {
+          _dateColumn = aData[0];
+        }
+        if (typeof _dateColumn == "string") {
+          _dateColumn = $(_dateColumn).attr("data-sort-value");
+        }
+        dateFilter = _dateColumn * 1000 >= minAge;
+      }
+      return dateFilter;
+    }
+
     $.fn.dataTableExt.sErrMode = "throw";
 
-    $.fn.dataTableExt.afnFiltering.push(PersistedButtonsFilters); // from dashboard-utils.js
+    $.fn.dataTableExt.afnFiltering.push(CoordinatorButtonsFilters);
 
     $(document).on("click", ".confirmationModal", function () {
       var _this = $(this);
@@ -349,8 +438,12 @@ ${layout.menubar(section='coordinators', dashboard=True)}
     var numRunning = 0;
 
     refreshRunning = function () {
-      $.getJSON(window.location.pathname + "?format=json&type=running", function (data) {
-        if (data.jobs) {
+      $.getJSON(window.location.pathname + "?format=json&offset=" + runningTableOffset + getStatuses('running'), function (data) {
+        // Refresh pagination buttons
+        totalRunningJobs = data.total_jobs;
+        refreshPaginationButtons("running", totalRunningJobs);
+
+        if (data.jobs.length > 0) {
           var nNodes = runningTable.fnGetNodes();
 
           // check for zombie nodes
@@ -430,8 +523,37 @@ ${layout.menubar(section='coordinators', dashboard=True)}
       });
     }
 
+    function refreshPaginationButtons(tableName, totalJobs) {
+      var prevBtn = $("a.btn-pagination[data-table='"+ tableName + "'][data-value='prev']");
+      var nextBtn = $("a.btn-pagination[data-table='"+ tableName + "'][data-value='next']");
+
+      var offset = runningTableOffset;
+      if (tableName == 'completed') {
+        offset = completedTableOffset;
+      }
+
+      if (offset == 1 || !totalJobs) {
+        prevBtn.parent().addClass("disabled");
+      }
+      else {
+        prevBtn.parent().removeClass("disabled");
+      }
+      if (totalJobs < (offset + PAGE_SIZE) || !totalJobs) {
+        nextBtn.parent().addClass("disabled");
+      }
+      else if (totalJobs >= offset + PAGE_SIZE) {
+        nextBtn.parent().removeClass("disabled");
+      }
+    }
+
+
     function refreshCompleted() {
-      $.getJSON(window.location.pathname + "?format=json&type=completed", function (data) {
+      $.getJSON(window.location.pathname + "?format=json&offset=" + completedTableOffset + getStatuses('completed'), function (data) {
+
+        // Refresh pagination buttons
+        totalCompletedJobs = data.total_jobs;
+        refreshPaginationButtons("completed", totalCompletedJobs);
+
         completedTable.fnClearTable();
         $(data.jobs).each(function (iWf, item) {
           var coord = new Coordinator(item);
@@ -461,7 +583,7 @@ ${layout.menubar(section='coordinators', dashboard=True)}
     }
 
     function refreshProgress() {
-      $.getJSON(window.location.pathname + "?format=json&type=progress", function (data) {
+      $.getJSON(window.location.pathname + "?format=json&type=progress" + getStatuses('running'), function (data) {
         var nNodes = runningTable.fnGetNodes();
           $(data.jobs).each(function (iCoord, item) {
             var coord = new Coordinator(item);

+ 2 - 2
apps/oozie/src/oozie/templates/dashboard/list_oozie_workflows.mako

@@ -515,10 +515,10 @@ ${ layout.menubar(section='workflows', dashboard=True) }
       else {
         prevBtn.parent().removeClass("disabled");
       }
-      if (totalJobs <= (offset + PAGE_SIZE) || !totalJobs) {
+      if (totalJobs < (offset + PAGE_SIZE) || !totalJobs) {
         nextBtn.parent().addClass("disabled");
       }
-      else if (totalJobs > offset + PAGE_SIZE) {
+      else if (totalJobs >= offset + PAGE_SIZE) {
         nextBtn.parent().removeClass("disabled");
       }
     }

+ 13 - 6
apps/oozie/src/oozie/views/dashboard.py

@@ -207,16 +207,23 @@ def list_oozie_coordinators(request):
   enable_cron_scheduling = ENABLE_CRON_SCHEDULING.get()
 
   if request.GET.get('format') == 'json':
-    if request.GET.get('type') in ('running', 'progress'):
-      kwargs['filters'].extend([('status', status) for status in CoordinatorWorkflow.RUNNING_STATUSES])
-    elif request.GET.get('type') == 'completed':
-      kwargs['filters'].extend([('status', status) for status in CoordinatorWorkflow.FINISHED_STATUSES])
+    if request.GET.get('offset'):
+      kwargs['offset'] = request.GET.get('offset')
+
+    json_jobs = []
+    total_jobs = 0
+    if request.GET.getlist('status'):
+      kwargs['filters'].extend([('status', status) for status in request.GET.getlist('status')])
+      co_list = oozie_api.get_coordinators(**kwargs)
+      json_jobs = co_list.jobs
+      total_jobs = co_list.total
 
-    json_jobs = oozie_api.get_coordinators(**kwargs).jobs
     if request.GET.get('type') == 'progress':
       json_jobs = [oozie_api.get_coordinator(job.id) for job in json_jobs]
 
-    return HttpResponse(json.dumps(massaged_oozie_jobs_for_json(json_jobs, request.user)).replace('\\\\', '\\'), content_type="application/json")
+    response = massaged_oozie_jobs_for_json(json_jobs, request.user)
+    response['total_jobs'] = total_jobs
+    return JsonResponse(response, encoder=JSONEncoderForHTML)
 
   return render('dashboard/list_oozie_coordinators.mako', request, {
     'jobs': [],