Browse Source

[assist] Introduced hueach binding for faster rendering times

Enrico Berti 10 years ago
parent
commit
76ea3a1

+ 9 - 0
desktop/core/src/desktop/static/desktop/css/hue3.css

@@ -2239,6 +2239,15 @@ div.navigator .pull-right .nav {
   background-color: #EEE;
   background-color: #EEE;
 }
 }
 
 
+.hueach {
+  position: relative;
+  width: 100%;
+}
+
+.valign-middle {
+  vertical-align: middle;
+}
+
 /*
 /*
 Transition to Hue 4
 Transition to Hue 4
 */
 */

+ 0 - 19
desktop/core/src/desktop/static/desktop/js/assist/assistDbEntry.js

@@ -74,25 +74,6 @@
       return self.entries().length > 0;
       return self.entries().length > 0;
     });
     });
 
 
-    self.entryLimit = ko.observable(500);
-    self.increasingLimit = ko.observable(false);
-
-    self.increaseLimit = function () {
-      self.increasingLimit(true);
-      window.setTimeout(function () {
-        self.entryLimit(self.entryLimit() + 500);
-        self.increasingLimit(false);
-      }, 100);
-    };
-
-    self.hasMoreEntries = ko.pureComputed(function () {
-      return self.limitedFilteredEntries().length < self.filteredEntries().length;
-    });
-
-    self.limitedFilteredEntries = ko.pureComputed(function () {
-      return self.filteredEntries().slice(0, self.entryLimit());
-    });
-
     self.filteredEntries = ko.pureComputed(function () {
     self.filteredEntries = ko.pureComputed(function () {
       if (self.filter == null || (self.filter.showTables && self.filter.showTables() && self.filter.showViews() && self.filter.query().length === 0)) {
       if (self.filter == null || (self.filter.showTables && self.filter.showTables() && self.filter.showViews() && self.filter.query().length === 0)) {
         return self.entries();
         return self.entries();

+ 70 - 0
desktop/core/src/desktop/static/desktop/js/ko.hue-bindings.js

@@ -951,6 +951,7 @@
           lastParentHeight = $parent.innerHeight();
           lastParentHeight = $parent.innerHeight();
           lastTop = $element.position().top;
           lastTop = $element.position().top;
           $element.height(lastParentHeight - lastTop - ($element.outerHeight(true) - $element.innerHeight()));
           $element.height(lastParentHeight - lastTop - ($element.outerHeight(true) - $element.innerHeight()));
+          huePubSub.publish('assist.stretchDown', $element);
         }
         }
       }, 200);
       }, 200);
     }
     }
@@ -2706,4 +2707,73 @@
     }
     }
   };
   };
 
 
+  ko.bindingHandlers.hueach = {
+    init: function (element, valueAccessor, allBindings) {
+      var valueAccessorBuilder = function () {
+        return {
+          data: ko.observableArray([])
+        }
+      }
+      ko.bindingHandlers.foreach.init(element, valueAccessorBuilder, allBindings);
+    },
+    update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
+      var $parent = $(element).parent(),
+        considerStretching = valueAccessor().considerStretching || false,
+        itemHeight = valueAccessor().itemHeight || 30,
+        scrollable = valueAccessor().scrollable || 'body',
+        renderTimeout = -1,
+        dataHasChanged = true;
+
+      if (!$parent.hasClass('hueach')) {
+        $(element).wrap('<div class="hueach"></div>');
+        $parent = $(element).parent();
+        $(element).css({
+          position: 'absolute',
+          width: '100%'
+        });
+      }
+
+      $parent.height(valueAccessor().data().length * itemHeight);
+      if (ko.utils.domData.get(element, 'originalData') && JSON.stringify(ko.utils.domData.get(element, 'originalData')) === JSON.stringify(valueAccessor().data())) {
+        dataHasChanged = false;
+      }
+      if (dataHasChanged) {
+        ko.utils.domData.set(element, 'originalData', valueAccessor().data());
+      }
+
+      var startItem = 0, endItem = 0;
+      var valueAccessorBuilder = function () {
+        return {
+          data: ko.utils.domData.get(element, 'originalData') ? ko.observableArray(ko.utils.domData.get(element, 'originalData').slice(startItem, endItem)) : []
+        }
+      }
+
+      var render = function () {
+        startItem = Math.floor($parent.parents(scrollable).scrollTop() / itemHeight);
+        endItem = startItem + Math.ceil($parent.parents(scrollable).height() / itemHeight);
+        $(element).css('top', (startItem * itemHeight) + 'px');
+        ko.bindingHandlers.foreach.update(element, valueAccessorBuilder, allBindings, viewModel, bindingContext);
+      }
+
+      $parent.parents(scrollable).on('scroll', function () {
+        window.clearTimeout(renderTimeout);
+        renderTimeout = window.setTimeout(render, 30);
+      });
+
+      if (considerStretching) {
+        huePubSub.subscribe('assist.stretchDown', function () {
+          window.clearTimeout(renderTimeout);
+          renderTimeout = window.setTimeout(function () {
+              ko.utils.domData.set(element, 'hasStretched', true);
+            render();
+          }, 300);
+        });
+      }
+
+      if (considerStretching && ko.utils.domData.get(element, 'hasStretched')) {
+        render();
+      }
+    }
+  };
+
 }));
 }));

+ 10 - 21
desktop/core/src/desktop/templates/assist.mako

@@ -279,7 +279,7 @@ from desktop.views import _ko
         <span data-bind="visible: navigationSettings.showStats, component: { name: 'table-stats', params: { statsVisible: statsVisible, sourceType: assistDbSource.type, snippet: assistDbSource.snippet, databaseName: databaseName, tableName: tableName, columnName: columnName, fieldType: definition.type, assistHelper: assistDbSource.assistHelper }}"></span>
         <span data-bind="visible: navigationSettings.showStats, component: { name: 'table-stats', params: { statsVisible: statsVisible, sourceType: assistDbSource.type, snippet: assistDbSource.snippet, databaseName: databaseName, tableName: tableName, columnName: columnName, fieldType: definition.type, assistHelper: assistDbSource.assistHelper }}"></span>
         <a class="inactive-action" href="javascript:void(0)" data-bind="visible: navigationSettings.openItem, click: openItem"><i class="fa fa-long-arrow-right" title="${_('Open')}"></i></a>
         <a class="inactive-action" href="javascript:void(0)" data-bind="visible: navigationSettings.openItem, click: openItem"><i class="fa fa-long-arrow-right" title="${_('Open')}"></i></a>
       </div>
       </div>
-      <a class="assist-entry assist-table-link" href="javascript:void(0)" data-bind="multiClick: { click: toggleOpen, dblClick: dblClick }, attr: {'title': definition.title }"><i class="fa fa-fw fa-table muted"></i><span draggable="true" data-bind="text: definition.displayName, draggableText: { text: editorText }"></span></a>
+      <a class="assist-entry assist-table-link" href="javascript:void(0)" data-bind="multiClick: { click: toggleOpen, dblClick: dblClick }, attr: {'title': definition.title }"><i class="fa fa-fw fa-table muted valign-middle"></i><span draggable="true" data-bind="text: definition.displayName, draggableText: { text: editorText }"></span></a>
       <div class="center" data-bind="visible: loading" style="display:none;"><i class="fa fa-spinner fa-spin assist-spinner"></i></div>
       <div class="center" data-bind="visible: loading" style="display:none;"><i class="fa fa-spinner fa-spin assist-spinner"></i></div>
       <!-- ko template: { if: open, name: 'assist-entries'  } --><!-- /ko -->
       <!-- ko template: { if: open, name: 'assist-entries'  } --><!-- /ko -->
     </li>
     </li>
@@ -291,14 +291,14 @@ from desktop.views import _ko
       <li class="assist-entry no-entries">${_('No results found')}</li>
       <li class="assist-entry no-entries">${_('No results found')}</li>
     </ul>
     </ul>
     <!-- /ko -->
     <!-- /ko -->
-    <ul data-bind="foreach: limitedFilteredEntries, css: { 'assist-tables': definition.isDatabase }">
+    <ul data-bind="hueach: {data: filteredEntries, itemHeight: 20, scrollable: '.assist-stretchable-list', considerStretching: true}, css: { 'assist-tables': definition.isDatabase }">
       <!-- ko template: { if: definition.isTable, name: 'assist-table-entry' } --><!-- /ko -->
       <!-- ko template: { if: definition.isTable, name: 'assist-table-entry' } --><!-- /ko -->
       <!-- ko ifnot: definition.isTable -->
       <!-- ko ifnot: definition.isTable -->
       <li data-bind="visibleOnHover: { override: statsVisible, selector: definition.isView ? '.table-actions' : '.column-actions' }, css: { 'assist-table': definition.isView, 'assist-column': definition.isColumn }">
       <li data-bind="visibleOnHover: { override: statsVisible, selector: definition.isView ? '.table-actions' : '.column-actions' }, css: { 'assist-table': definition.isView, 'assist-column': definition.isColumn }">
         <!-- ko template: { if: definition.isView || definition.isColumn, name: 'assist-entry-actions' } --><!-- /ko -->
         <!-- ko template: { if: definition.isView || definition.isColumn, name: 'assist-entry-actions' } --><!-- /ko -->
         <a class="assist-entry" href="javascript:void(0)" data-bind="multiClick: { click: toggleOpen, dblClick: dblClick }, attr: {'title': definition.title }, css: { 'assist-field-link': !definition.isView, 'assist-table-link': definition.isView }">
         <a class="assist-entry" href="javascript:void(0)" data-bind="multiClick: { click: toggleOpen, dblClick: dblClick }, attr: {'title': definition.title }, css: { 'assist-field-link': !definition.isView, 'assist-table-link': definition.isView }">
           <!-- ko if: definition.isView -->
           <!-- ko if: definition.isView -->
-            <i class="fa fa-fw fa-eye muted"></i>
+            <i class="fa fa-fw fa-eye muted valign-middle"></i>
           <!-- /ko -->
           <!-- /ko -->
           <span draggable="true" data-bind="text: definition.displayName, draggableText: { text: editorText }"></span>
           <span draggable="true" data-bind="text: definition.displayName, draggableText: { text: editorText }"></span>
         </a>
         </a>
@@ -307,17 +307,6 @@ from desktop.views import _ko
       </li>
       </li>
       <!-- /ko -->
       <!-- /ko -->
     </ul>
     </ul>
-    <!-- ko if: hasMoreEntries -->
-    <ul class="assist-tables">
-      <li>
-        <div class="assist-show-more" data-bind="visible: ! increasingLimit()" style="display: none;">
-          ${_('Showing')} <span data-bind="text: limitedFilteredEntries().length"></span> ${_('of')} <span data-bind="text: filteredEntries().length"></span> -
-          <a href="javascript:void(0);" data-bind="click: increaseLimit">${_('Show more')}...</a>
-        </div>
-        <div class="center" data-bind="visible: increasingLimit" style="display:none;"><i class="fa fa-spinner fa-spin assist-spinner"></i></div>
-      </li>
-    </ul>
-    <!-- /ko -->
     <!-- ko template: { if: ! hasEntries() && ! loading() && (definition.isTable || definition.isView), name: 'assist-no-table-entries' } --><!-- /ko -->
     <!-- ko template: { if: ! hasEntries() && ! loading() && (definition.isTable || definition.isView), name: 'assist-no-table-entries' } --><!-- /ko -->
     <!-- ko template: { if: ! hasEntries() && ! loading() && definition.isDatabase, name: 'assist-no-database-entries' } --><!-- /ko -->
     <!-- ko template: { if: ! hasEntries() && ! loading() && definition.isDatabase, name: 'assist-no-database-entries' } --><!-- /ko -->
   </script>
   </script>
@@ -388,7 +377,7 @@ from desktop.views import _ko
         </li>
         </li>
 
 
         <li>
         <li>
-          <ul class="assist-tables" data-bind="foreach: entries">
+          <ul class="assist-tables" data-bind="hueach: {data: entries, itemHeight: 20, scrollable: '.assist-stretchable-list', considerStretching: true}">
             <li class="assist-entry assist-table-link" style="position: relative;" data-bind="visibleOnHover: { 'selector': '.assist-actions' }">
             <li class="assist-entry assist-table-link" style="position: relative;" data-bind="visibleOnHover: { 'selector': '.assist-actions' }">
               <div class="assist-actions table-actions" style="opacity: 0;" >
               <div class="assist-actions table-actions" style="opacity: 0;" >
                 <a style="padding: 0 3px;" class="inactive-action" href="javascript:void(0);" data-bind="templatePopover : { contentTemplate: 'hdfs-details-content', titleTemplate: 'hdfs-details-title', minWidth: '320px' }">
                 <a style="padding: 0 3px;" class="inactive-action" href="javascript:void(0);" data-bind="templatePopover : { contentTemplate: 'hdfs-details-content', titleTemplate: 'hdfs-details-title', minWidth: '320px' }">
@@ -398,10 +387,10 @@ from desktop.views import _ko
 
 
               <a href="javascript:void(0)" class="assist-entry assist-table-link" data-bind="multiClick: { click: toggleOpen, dblClick: dblClick }, attr: {'title': definition.name }">
               <a href="javascript:void(0)" class="assist-entry assist-table-link" data-bind="multiClick: { click: toggleOpen, dblClick: dblClick }, attr: {'title': definition.name }">
                 <!-- ko if: definition.type === 'dir' -->
                 <!-- ko if: definition.type === 'dir' -->
-                <i class="fa fa-fw fa-folder muted"></i>
+                <i class="fa fa-fw fa-folder muted valign-middle"></i>
                 <!-- /ko -->
                 <!-- /ko -->
                 <!-- ko if: definition.type === 'file' -->
                 <!-- ko if: definition.type === 'file' -->
-                <i class="fa fa-fw fa-file-o muted"></i>
+                <i class="fa fa-fw fa-file-o muted valign-middle"></i>
                 <!-- /ko -->
                 <!-- /ko -->
                 <span draggable="true" data-bind="text: definition.name, draggableText: { text: '\'' + path + '\'' }"></span>
                 <span draggable="true" data-bind="text: definition.name, draggableText: { text: '\'' + path + '\'' }"></span>
               </a>
               </a>
@@ -445,7 +434,7 @@ from desktop.views import _ko
             <img src="${ static('impala/art/icon_impala_48.png') }" class="assist-icon"/>
             <img src="${ static('impala/art/icon_impala_48.png') }" class="assist-icon"/>
             <!-- /ko -->
             <!-- /ko -->
             <!-- ko if: type == 'notebook' -->
             <!-- ko if: type == 'notebook' -->
-            <i class="fa fa-fw fa-tags muted"></i>
+            <i class="fa fa-fw fa-tags muted valign-middle"></i>
             <!-- /ko -->
             <!-- /ko -->
             <!-- ko if: type == 'oozie-workflow2' -->
             <!-- ko if: type == 'oozie-workflow2' -->
             <img src="${ static('oozie/art/icon_oozie_workflow_48.png') }" class="assist-icon"/>
             <img src="${ static('oozie/art/icon_oozie_workflow_48.png') }" class="assist-icon"/>
@@ -457,7 +446,7 @@ from desktop.views import _ko
             <img src="${ static('oozie/art/icon_oozie_bundle_48.png') }" class="assist-icon"/>
             <img src="${ static('oozie/art/icon_oozie_bundle_48.png') }" class="assist-icon"/>
             <!-- /ko -->
             <!-- /ko -->
             <!-- ko if: type == 'search-dashboard' -->
             <!-- ko if: type == 'search-dashboard' -->
-            <i class="fa fa-fw fa-search muted"></i>
+            <i class="fa fa-fw fa-search muted valign-middle"></i>
             <!-- /ko -->
             <!-- /ko -->
 
 
             <span data-bind="text: name"></span>
             <span data-bind="text: name"></span>
@@ -515,7 +504,7 @@ from desktop.views import _ko
     </ul>
     </ul>
     <ul class="nav assist-stretchable-list" data-bind="stretchDown">
     <ul class="nav assist-stretchable-list" data-bind="stretchDown">
       <li data-bind="visible: ! hasErrors()" >
       <li data-bind="visible: ! hasErrors()" >
-        <ul class="assist-tables" data-bind="foreach: filteredEntries">
+        <ul class="assist-tables" data-bind="hueach: {data: filteredEntries, itemHeight: 20, scrollable: '.assist-stretchable-list', considerStretching: true}">
           <li class="assist-table pointer" data-bind="visibleOnHover: { selector: '.database-actions' }">
           <li class="assist-table pointer" data-bind="visibleOnHover: { selector: '.database-actions' }">
             <!-- ko template: { name: 'assist-entry-actions' } --><!-- /ko -->
             <!-- ko template: { name: 'assist-entry-actions' } --><!-- /ko -->
             <a class="assist-table-link" href="javascript: void(0);" data-bind="text: definition.name, click: function () { $parent.selectedDatabase($data) }"></a>
             <a class="assist-table-link" href="javascript: void(0);" data-bind="text: definition.name, click: function () { $parent.selectedDatabase($data) }"></a>
@@ -612,7 +601,7 @@ from desktop.views import _ko
     <div class="assist-panel-switches assist-fixed-height" style="display:none;">
     <div class="assist-panel-switches assist-fixed-height" style="display:none;">
       <!-- ko foreach: availablePanels -->
       <!-- ko foreach: availablePanels -->
       <div class="inactive-action assist-type-switch" data-bind="click: function () { visible(!visible()) }, css: { 'blue': visible }, attr: { 'title': visible() ? '${ _('Hide') } ' + name : '${ _('Show') } ' + name }">
       <div class="inactive-action assist-type-switch" data-bind="click: function () { visible(!visible()) }, css: { 'blue': visible }, attr: { 'title': visible() ? '${ _('Hide') } ' + name : '${ _('Show') } ' + name }">
-        <i class="fa fa-fw" data-bind="css: icon"></i>
+        <i class="fa fa-fw valign-middle" data-bind="css: icon"></i>
       </div>
       </div>
       <!-- /ko -->
       <!-- /ko -->
     </div>
     </div>