Pārlūkot izejas kodu

[spark] Support for running new queries in the same snipper and row numbers

Enrico Berti 11 gadi atpakaļ
vecāks
revīzija
20e6c95

+ 44 - 19
apps/spark/src/spark/templates/editor.mako

@@ -218,21 +218,18 @@ ${ commonheader(_('Query'), app_name, user, "68px") | n,unicode }
             <li class="nav-header">${_('columns')}</li>
             <li class="nav-header">${_('columns')}</li>
           </ul>
           </ul>
           <ul class="unstyled" data-bind="foreach: result.meta">
           <ul class="unstyled" data-bind="foreach: result.meta">
-            <li><input type="checkbox" checked="checked" data-bind="event: { change: function(){toggleColumn($element, $index());}}" /> <a class="pointer" data-bind="text: $data.name, click: function(){ scrollToColumn($element, $index()); }"></a></li>
+            <li data-bind="visible: name != ''"><input type="checkbox" checked="checked" data-bind="event: { change: function(){toggleColumn($element, $index());}}" /> <a class="pointer" data-bind="text: $data.name, click: function(){ scrollToColumn($element, $index()); }"></a></li>
           </ul>
           </ul>
         </div>
         </div>
         <div class="span10">
         <div class="span10">
           <div data-bind="css: resultsKlass">
           <div data-bind="css: resultsKlass">
-            <table class="table table-condensed">
+            <table class="table table-condensed resultTable">
               <thead>
               <thead>
-                <tr data-bind="foreach: {data: result.meta, afterAdd: waitForDatatable}">
-                  <th data-bind="text: $data.name"></th>
+                <tr data-bind="foreach: result.meta">
+                  <th data-bind="html: ($index() == 0 ? '&nbsp;' : $data.name), css: { 'sort-numeric': isNumericColumn($data.type), 'sort-date': isDateTimeColumn($data.type), 'sort-string': isStringColumn($data.type)}"></th>
                 </tr>
                 </tr>
               </thead>
               </thead>
-              <tbody data-bind="foreach: {data: result.data, afterAdd: waitForDatatable}">
-                <tr data-bind="foreach: $data">
-                  <td data-bind="text: $data" class="nowrap"></td>
-                </tr>
+              <tbody>
               </tbody>
               </tbody>
             </table>
             </table>
             
             
@@ -762,12 +759,9 @@ ${ commonheader(_('Query'), app_name, user, "68px") | n,unicode }
     $(".assist-main").height($(window).height() - 230);
     $(".assist-main").height($(window).height() - 230);
   }
   }
 
 
-  var _datatableCreationTimeout = -1;
-  function waitForDatatable(el) {
-    if ($(el).is("tr") && $(el).parents("table").length > 0){
-      window.clearTimeout(_datatableCreationTimeout);
-      _datatableCreationTimeout = window.setTimeout(function(){
-        $(el).parents("table").dataTable({
+  function createDatatable(el, snippet) {
+        $(el).addClass("dt");
+        var _dt = $(el).dataTable({
         "bPaginate": false,
         "bPaginate": false,
         "bLengthChange": false,
         "bLengthChange": false,
         "bInfo": false,
         "bInfo": false,
@@ -778,12 +772,12 @@ ${ commonheader(_('Query'), app_name, user, "68px") | n,unicode }
           "sZeroRecords": "${_('No matching records')}"
           "sZeroRecords": "${_('No matching records')}"
         },
         },
         "fnDrawCallback": function (oSettings) {
         "fnDrawCallback": function (oSettings) {
-          $(el).parents("table").find(".dataTables_wrapper").jHueTableScroller({
+          $(el).parents(".dataTables_wrapper").jHueTableScroller({
             minHeight: $(window).height() - 400,
             minHeight: $(window).height() - 400,
             heightAfterCorrection: 0
             heightAfterCorrection: 0
           });
           });
 
 
-          $(el).parents("table").jHueTableExtender({
+          $(el).jHueTableExtender({
             fixedHeader: true,
             fixedHeader: true,
             includeNavigator: false
             includeNavigator: false
           });
           });
@@ -808,13 +802,12 @@ ${ commonheader(_('Query'), app_name, user, "68px") | n,unicode }
           heightAfterCorrection: 0
           heightAfterCorrection: 0
         });
         });
 
 
-        $(el).parents("table").jHueTableExtender({
+        $(el).jHueTableExtender({
           fixedHeader: true,
           fixedHeader: true,
           includeNavigator: false
           includeNavigator: false
         });
         });
         $(".dataTables_filter").hide();
         $(".dataTables_filter").hide();
-      }, 100);
-    }
+    return _dt;
   }
   }
 
 
   function toggleColumn(linkElement, index){
   function toggleColumn(linkElement, index){
@@ -838,8 +831,40 @@ ${ commonheader(_('Query'), app_name, user, "68px") | n,unicode }
     }
     }
   }
   }
 
 
+  function isNumericColumn(type) {
+    return $.inArray(type, ['TINYINT_TYPE', 'SMALLINT_TYPE', 'INT_TYPE', 'BIGINT_TYPE', 'FLOAT_TYPE', 'DOUBLE_TYPE', 'DECIMAL_TYPE', 'TIMESTAMP_TYPE', 'DATE_TYPE']) > -1;
+  }
+
+  function isDateTimeColumn(type) {
+    return $.inArray(type, ['TIMESTAMP_TYPE', 'DATE_TYPE']) > -1;
+  }
+
+  function isStringColumn(type) {
+    return !isNumericColumn(type) && !isDateTimeColumn(type);
+  }
+
   $(document).ready(function(){
   $(document).ready(function(){
     resizeAssist();
     resizeAssist();
+    $(document).on("executeStarted", function(e, snippet){
+      var _el = $("#snippet_"+snippet.id()).find(".resultTable");
+      if (_el.hasClass("dt")){
+        _el.removeClass("dt");
+        $("#eT" + snippet.id() + "jHueTableExtenderClonedContainer").remove();
+        _el.dataTable().fnClearTable();
+        _el.dataTable().fnDestroy();
+        _el.find("thead tr").empty();
+      }
+    });
+
+    $(document).on("renderData", function(e, options){
+      var _el = $("#snippet_"+options.snippet.id).find(".resultTable");
+      if (options.data.length > 0){
+        window.setTimeout(function(){
+          var _dt = createDatatable(_el, options.snippet);
+          _dt.fnAddData(options.data)
+        }, 10);
+      }
+    });
   });
   });
 
 
 </script>
 </script>

+ 4 - 0
apps/spark/static/css/spark.css

@@ -125,4 +125,8 @@
 
 
 .editable-empty, .editable-empty:hover {
 .editable-empty, .editable-empty:hover {
   color: #DDD!important;
   color: #DDD!important;
+}
+
+.results table tr td {
+  white-space: nowrap;
 }
 }

+ 20 - 7
apps/spark/static/js/spark.vm.js

@@ -21,9 +21,19 @@ var Result = function (snippet, result) {
   self.id = ko.observable(typeof result.id != "undefined" && result.id != null ? result.id : UUID());
   self.id = ko.observable(typeof result.id != "undefined" && result.id != null ? result.id : UUID());
   self.type = ko.observable(typeof result.type != "undefined" && result.type != null ? result.type : 'table');
   self.type = ko.observable(typeof result.type != "undefined" && result.type != null ? result.type : 'table');
   self.handle = ko.observable({});
   self.handle = ko.observable({});
-  self.meta = ko.mapping.fromJS(typeof result.meta != "undefined" && result.meta != null ? result.meta : []);
-  self.data = ko.mapping.fromJS(typeof result.data != "undefined" && result.data != null ? result.data : []);
+  self.meta = ko.observableArray(typeof result.meta != "undefined" && result.meta != null ? result.meta : []);
+  self.meta.extend({ rateLimit: 50 });
+  self.data = ko.observableArray(typeof result.data != "undefined" && result.data != null ? result.data : []);
+  self.data.extend({ rateLimit: 50 });
   self.logs = ko.observable('');
   self.logs = ko.observable('');
+
+  self.meta.subscribe(function(val){
+    $(document).trigger("renderMeta", {data: val, snippet: snippet});
+  });
+
+  self.data.subscribe(function(val){
+    $(document).trigger("renderData", {data: val, snippet: snippet});
+  });
   
   
   if (typeof result.handle != "undefined" && result.handle != null) {
   if (typeof result.handle != "undefined" && result.handle != null) {
     $.each(result.handle, function(key, val) {
     $.each(result.handle, function(key, val) {
@@ -198,11 +208,12 @@ var Snippet = function (notebook, snippet) {
   };
   };
   
   
   self.execute = function() {
   self.execute = function() {
-	$(".jHueNotify").hide();
-	logGA('/execute/' + self.type());	  
+    $(document).trigger("executeStarted", self);
+	  $(".jHueNotify").hide();
+	  logGA('/execute/' + self.type());
     
     
-	self.result.clear();
-	self.status('running');
+	  self.result.clear();
+	  self.status('running');
     
     
     $.post("/spark/api/execute", {
     $.post("/spark/api/execute", {
         notebook: ko.mapping.toJSON(notebook),
         notebook: ko.mapping.toJSON(notebook),
@@ -257,9 +268,11 @@ var Snippet = function (notebook, snippet) {
     }, function (data) {
     }, function (data) {
  	  if (data.status == 0) {
  	  if (data.status == 0) {
  	    rows -= data.result.data.length;
  	    rows -= data.result.data.length;
+      data.result.meta.unshift({ type:"INT_TYPE", name:"", comment:null});
  	    self.result.meta(data.result.meta);
  	    self.result.meta(data.result.meta);
  	    $.each(data.result.data, function(index, row) {
  	    $.each(data.result.data, function(index, row) {
- 	      self.result.data.push(row);  
+        row.unshift(index);
+ 	      self.result.data.push(row);
  	    });
  	    });
          
          
         if (data.result.hasMore && rows > 0) {
         if (data.result.hasMore && rows > 0) {

+ 4 - 4
desktop/core/static/ext/js/jquery/plugins/jquery.dataTables.1.8.2.min.js

@@ -3,14 +3,14 @@
  * Version:     1.8.2
  * Version:     1.8.2
  * Author:      Allan Jardine (www.sprymedia.co.uk)
  * Author:      Allan Jardine (www.sprymedia.co.uk)
  * Info:        www.datatables.net
  * Info:        www.datatables.net
- * 
+ *
  * Copyright 2008-2011 Allan Jardine, all rights reserved.
  * Copyright 2008-2011 Allan Jardine, all rights reserved.
  *
  *
  * This source file is free software, under either the GPL v2 license or a
  * This source file is free software, under either the GPL v2 license or a
  * BSD style license, as supplied with this software.
  * BSD style license, as supplied with this software.
- * 
- * This source file is distributed in the hope that it will be useful, but 
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
+ *
+ * This source file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
  * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
  */
  */
 (function(i,za,p){i.fn.dataTableSettings=[];var D=i.fn.dataTableSettings;i.fn.dataTableExt={};var n=i.fn.dataTableExt;n.sVersion="1.8.2";n.sErrMode="alert";n.iApiIndex=0;n.oApi={};n.afnFiltering=[];n.aoFeatures=[];n.ofnSearch={};n.afnSortData=[];n.oStdClasses={sPagePrevEnabled:"paginate_enabled_previous",sPagePrevDisabled:"paginate_disabled_previous",sPageNextEnabled:"paginate_enabled_next",sPageNextDisabled:"paginate_disabled_next",sPageJUINext:"",sPageJUIPrev:"",sPageButton:"paginate_button",sPageButtonActive:"paginate_active",
 (function(i,za,p){i.fn.dataTableSettings=[];var D=i.fn.dataTableSettings;i.fn.dataTableExt={};var n=i.fn.dataTableExt;n.sVersion="1.8.2";n.sErrMode="alert";n.iApiIndex=0;n.oApi={};n.afnFiltering=[];n.aoFeatures=[];n.ofnSearch={};n.afnSortData=[];n.oStdClasses={sPagePrevEnabled:"paginate_enabled_previous",sPagePrevDisabled:"paginate_disabled_previous",sPageNextEnabled:"paginate_enabled_next",sPageNextDisabled:"paginate_disabled_next",sPageJUINext:"",sPageJUIPrev:"",sPageButton:"paginate_button",sPageButtonActive:"paginate_active",