فهرست منبع

HUE-3294 [core] Convert snippet-db-selection ko component to a generic hue-drop-down

Johan Ahlen 9 سال پیش
والد
کامیت
61f96a8ac7

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

@@ -2410,6 +2410,16 @@ body {
   border-bottom: 1px solid #DDD;
 }
 
+.hue-drop-down-input {
+  width: 175px !important;
+  height: 12px !important;
+  font-size: 12px !important;
+  border: 1px solid rgba(0,0,0,0.2) !important;
+  border-radius: 2px !important;
+  box-shadow: none !important;
+  margin-left: -1px;
+}
+
 .hue-context-menu {
   display: none;
   position: fixed;

+ 5 - 0
desktop/core/src/desktop/templates/common_header.mako

@@ -24,6 +24,9 @@ home_url = url('desktop.views.home')
 if USE_NEW_EDITOR.get():
   home_url = url('desktop.views.home2')
 %>
+
+<%namespace name="koComponents" file="/ko_components.mako" />
+
 <!DOCTYPE html>
 <%def name="is_selected(selected)">
   %if selected:
@@ -217,6 +220,8 @@ if USE_NEW_EDITOR.get():
   <script src="${ static('desktop/ext/js/knockout-mapping.min.js') }"></script>
   <script src="${ static('desktop/js/ko.hue-bindings.js') }"></script>
 
+  ${ koComponents.all() }
+
   <script type="text/javascript" charset="utf-8">
 
     moment.locale(window.navigator.userLanguage || window.navigator.language);

+ 160 - 0
desktop/core/src/desktop/templates/ko_components.mako

@@ -0,0 +1,160 @@
+## Licensed to Cloudera, Inc. under one
+## or more contributor license agreements.  See the NOTICE file
+## distributed with this work for additional information
+## regarding copyright ownership.  Cloudera, Inc. 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.
+
+<%!
+from desktop import conf
+from desktop.lib.i18n import smart_unicode
+from django.utils.translation import ugettext as _
+from desktop.views import _ko
+%>
+
+<%def name="all()">
+  <script type="text/html" id="hue-drop-down-template">
+    <!-- ko if: !dropDownVisible() || !searchable -->
+    <a class="inactive-action active-database margin-left-10" href="javascript:void(0)" data-bind="toggle: dropDownVisible, css: { 'blue': dropDownVisible }">
+      <span data-bind="text: value, visible: ! dropDownVisible()"  title="${ _('Selected database') }"></span>
+      <i class="fa fa-caret-down"></i>
+    </a>
+    <!-- /ko -->
+    <!-- ko if: dropDownVisible() && searchable -->
+    <input class="hue-drop-down-input" type="text" data-bind="textInput: filter, attr: { 'placeHolder': value }, visible: dropDownVisible, style: { color: filterEdited() ? '#000' : '#AAA', 'min-height': '22px', 'margin-left': '10px' }"/>
+    <i class="fa fa-caret-down"></i>
+    <!-- /ko -->
+    <div data-bind="css: { 'open' : dropDownVisible }" style="position: absolute;">
+      <div class="dropdown-menu" data-bind="visible: filteredEntries().length > 0" style="overflow-y: scroll; width: 190px; margin-left: 10px; min-height: 34px; max-height: 200px;">
+        <!-- ko if: foreachVisible -->
+        <ul class="hue-inner-drop-down" data-bind="foreachVisible: { data: filteredEntries, minHeight: 34, container: '.dropdown-menu' }">
+          <li><a href="javascript:void(0)" data-bind="text: $data, click: function () { $parent.value($data); }"></a></li>
+        </ul>
+        <!-- /ko -->
+        <!-- ko ifnot: foreachVisible -->
+        <ul class="hue-inner-drop-down" data-bind="foreach: filteredEntries">
+          <li><a href="javascript:void(0)" data-bind="text: $data, click: function () { $parent.value($data); }"></a></li>
+        </ul>
+        <!-- /ko -->
+      </div>
+    </div>
+  </script>
+
+  <script type="text/javascript" charset="utf-8">
+    (function () {
+      var HueDropDown = function (params, element) {
+        var self = this;
+        self.dropDownVisible = ko.observable(false);
+        self.value = params.value;
+        self.entries = params.entries;
+        self.searchable = params.searchable || false;
+        self.foreachVisible = params.foreachVisible || false;
+
+        var closeOnOutsideClick = function (e) {
+          var $input = $(element).find('.hue-drop-down-input');
+          if (!$input.is($(e.target))) {
+            self.dropDownVisible(false);
+          }
+        };
+
+        var inputKeyup = function (e) {
+          var $currentActive = $(element).find('.hue-inner-drop-down > .active');
+          var activeTop = $currentActive.length !== 0 ? $currentActive.position().top : 0;
+          var activeHeight = $currentActive.length !== 0 ? $currentActive.outerHeight(true) : $(element).find('.hue-inner-drop-down li:first-child').outerHeight(true);
+          var containerHeight = $(element).find('.dropdown-menu').innerHeight();
+          var containerScrollTop = $(element).find('.dropdown-menu').scrollTop();
+
+          $currentActive.removeClass('active');
+          if (e.keyCode === 27) {
+            // esc
+            self.dropDownVisible(false);
+          } else if (e.keyCode === 38) {
+            // up
+            if ($currentActive.length !== 0 && $currentActive.prev().length !== 0) {
+              if (activeTop < containerScrollTop + activeHeight) {
+                $(element).find('.dropdown-menu').scrollTop(activeTop - containerHeight/2);
+              }
+              $currentActive.prev().addClass('active');
+            }
+          } else if (e.keyCode === 40) {
+            // down
+            if ($currentActive.length === 0) {
+              $(element).find('.hue-inner-drop-down li:first-child').addClass('active');
+            } else if ($currentActive.next().length !== 0) {
+              if ((activeTop + activeHeight *3) > containerHeight - containerScrollTop) {
+                $(element).find('.dropdown-menu').scrollTop(activeTop - containerHeight/2);
+              }
+              $currentActive.next().addClass('active');
+            } else {
+              $currentActive.addClass('active');
+            }
+          } else if (e.keyCode === 13) {
+            // enter
+            if ($currentActive.length > 0) {
+              self.value(ko.dataFor($currentActive[0]));
+              self.dropDownVisiblele(false);
+              $(element).find('.dropdown-menu').scrollTop(0)
+            }
+          } else {
+            $(element).find('.dropdown-menu').scrollTop(0)
+          }
+        };
+        self.filter = ko.observable('');
+
+        self.value.subscribe(function () {
+          self.dropDownVisible(false);
+        });
+
+        self.filterEdited = ko.observable(false);
+
+        self.filter.subscribe(function () {
+          self.filterEdited(true);
+          $(element).find('.hue-inner-drop-down > .active').removeClass('.active');
+        });
+        self.dropDownVisible.subscribe(function (newValue) {
+          self.filterEdited(false);
+          if (newValue) {
+            window.setTimeout(function () {
+              self.filter('');
+              $(window).on('click', closeOnOutsideClick);
+              $(element).find('.hue-drop-down-input').on('keyup', inputKeyup);
+              $(element).find('.hue-drop-down-input').focus();
+            }, 0);
+          } else {
+            $(element).find('.hue-inner-drop-down > .active').removeClass('.active');
+            $(window).off('click', closeOnOutsideClick);
+            $(element).find('.hue-drop-down-input').off('keyup', inputKeyup);
+          }
+        });
+        self.filteredEntries = ko.pureComputed(function () {
+          if (self.filter() === '' || ! self.filterEdited()) {
+            return self.entries();
+          } else {
+            var lowerFilter = self.filter().toLowerCase();
+            return self.entries().filter(function (database) {
+              return database.toLowerCase().indexOf(lowerFilter) !== -1;
+            });
+          }
+        });
+      };
+
+      ko.components.register('hue-drop-down', {
+        viewModel: {
+          createViewModel: function(params, componentInfo) {
+            return new HueDropDown(params, componentInfo.element);
+          }
+        },
+        template: { element: 'hue-drop-down-template' }
+      });
+    })();
+  </script>
+</%def>

+ 2 - 1
desktop/core/src/desktop/templates/responsive.mako

@@ -22,6 +22,7 @@
   from metadata.conf import has_optimizer
 %>
 
+<%namespace name="koComponents" file="/ko_components.mako" />
 <%namespace name="assist" file="/assist.mako" />
 <%namespace name="hueIcons" file="/hue_icons.mako" />
 
@@ -333,8 +334,8 @@ ${ hueIcons.symbols() }
 <script src="${ static('desktop/js/jquery.scrollup.js') }"></script>
 <script src="${ static('desktop/js/sqlFunctions.js') }"></script>
 
+${ koComponents.all() }
 ${ assist.assistJSModels() }
-
 ${ assist.assistPanel() }
 
 <script type="text/javascript" charset="utf-8">

+ 0 - 1
desktop/libs/notebook/src/notebook/templates/editor.mako

@@ -42,7 +42,6 @@ ${ assist.assistPanel() }
 ${ assist.assistJSModels() }
 ${ configKoComponents.config() }
 ${ notebookKoComponents.downloadSnippetResults() }
-${ notebookKoComponents.snippetDbSelection() }
 
 ${ editorComponents.commonJS() }
 </span>

+ 1 - 1
desktop/libs/notebook/src/notebook/templates/editor_components.mako

@@ -1461,7 +1461,7 @@ ${ hueIcons.symbols() }
     <!-- ko template: { name: 'longer-operation' } --><!-- /ko -->
     <span class="execution-timer" data-bind="visible: type() != 'text' && status() != 'ready' && status() != 'loading', text: result.executionTime().toHHMMSS()" title="${ _('Execution time') }"></span>
     <!-- ko if: availableDatabases().length > 0 && isSqlDialect() -->
-    <div data-bind="component: { name: 'snippet-db-selection', params: { selectedDatabase: database, availableDatabases: availableDatabases } }" style="display: inline-block"></div>
+    <div data-bind="component: { name: 'hue-drop-down', params: { value: database, entries: availableDatabases, foreachVisible: true, searchable: true } }" style="display: inline-block"></div>
     <!-- /ko -->
 
    <!-- ko template: { name: 'snippet-header-statement-type' } --><!-- /ko -->

+ 0 - 1
desktop/libs/notebook/src/notebook/templates/editor_embeddable.mako

@@ -38,7 +38,6 @@ ${ editorComponents.commonHTML(with_assist=False) }
 
 ${ configKoComponents.config() }
 ${ notebookKoComponents.downloadSnippetResults() }
-${ notebookKoComponents.snippetDbSelection() }
 
 ${ editorComponents.commonJS(is_embeddable=True) }
 

+ 0 - 1
desktop/libs/notebook/src/notebook/templates/notebook.mako

@@ -52,7 +52,6 @@ ${ assist.assistJSModels() }
 ${ configKoComponents.config() }
 ${ notebookKoComponents.addSnippetMenu() }
 ${ notebookKoComponents.downloadSnippetResults() }
-${ notebookKoComponents.snippetDbSelection() }
 
 ${ editorComponents.commonJS() }
 

+ 0 - 141
desktop/libs/notebook/src/notebook/templates/notebook_ko_components.mako

@@ -34,147 +34,6 @@ except ImportError, e:
   ENABLE_NEW_INDEXER = None
 %>
 
-<%def name="snippetDbSelection()">
-  <style>
-    .db-selection-input {
-      width: 175px !important;
-      height: 12px !important;
-      font-size: 12px !important;
-      border: 1px solid rgba(0,0,0,0.2) !important;
-      border-radius: 2px !important;
-      box-shadow: none !important;
-      margin-left: -1px;
-    }
-  </style>
-
-  <script type="text/html" id="snippet-db-selection-template">
-    <!-- ko ifnot: dbSelectionVisible -->
-    <a class="inactive-action active-database margin-left-10" href="javascript:void(0)" data-bind="toggle: dbSelectionVisible, css: { 'blue': dbSelectionVisible }">
-      <span data-bind="text: selectedDatabase, visible: ! dbSelectionVisible()"  title="${ _('Selected database') }"></span>
-      <i class="fa fa-caret-down"></i>
-    </a>
-    <!-- /ko -->
-    <!-- ko if: dbSelectionVisible -->
-    <input class="db-selection-input" type="text" data-bind="textInput: filter, attr: { 'placeHolder': selectedDatabase }, visible: dbSelectionVisible, style: { color: filterEdited() ? '#000' : '#AAA', 'min-height': '22px', 'margin-left': '10px' }"/>
-    <i class="fa fa-caret-down"></i>
-    <!-- /ko -->
-    <div data-bind="css: { 'open' : dbSelectionVisible }" style="position: absolute;">
-      <div class="dropdown-menu" data-bind="visible: filteredDatabases().length > 0" style="overflow-y: scroll; width: 190px; margin-left: 10px; min-height: 34px; max-height: 200px;">
-        <ul class="hue-inner-drop-down" data-bind="foreachVisible: { data: filteredDatabases, minHeight: 34, container: '.dropdown-menu' }">
-          <li><a href="javascript:void(0)" data-bind="text: $data, click: function () { $parent.selectedDatabase($data); }"></a></li>
-        </ul>
-      </div>
-    </div>
-  </script>
-
-  <script type="text/javascript" charset="utf-8">
-    (function () {
-      var SnippetDbSelection = function (params, element) {
-        var self = this;
-        self.dbSelectionVisible = ko.observable(false);
-        self.selectedDatabase = params.selectedDatabase;
-        self.availableDatabases = params.availableDatabases;
-
-        var closeOnOutsideClick = function (e) {
-          var $input = $(element).find('.db-selection-input');
-          if (!$input.is($(e.target))) {
-            self.dbSelectionVisible(false);
-          }
-        };
-
-        var inputKeyup = function (e) {
-          var $currentActive = $(element).find('.hue-inner-drop-down > .active');
-          var activeTop = $currentActive.length !== 0 ? $currentActive.position().top : 0;
-          var activeHeight = $currentActive.length !== 0 ? $currentActive.outerHeight(true) : $(element).find('.hue-inner-drop-down li:first-child').outerHeight(true);
-          var containerHeight = $(element).find('.dropdown-menu').innerHeight();
-          var containerScrollTop = $(element).find('.dropdown-menu').scrollTop();
-
-          $currentActive.removeClass('active');
-          if (e.keyCode === 27) {
-            // esc
-            self.dbSelectionVisible(false);
-          } else if (e.keyCode === 38) {
-            // up
-            if ($currentActive.length !== 0 && $currentActive.prev().length !== 0) {
-              if (activeTop < containerScrollTop + activeHeight) {
-                $(element).find('.dropdown-menu').scrollTop(activeTop - containerHeight/2);
-              }
-              $currentActive.prev().addClass('active');
-            }
-          } else if (e.keyCode === 40) {
-            // down
-            if ($currentActive.length === 0) {
-              $(element).find('.hue-inner-drop-down li:first-child').addClass('active');
-            } else if ($currentActive.next().length !== 0) {
-              if ((activeTop + activeHeight *3) > containerHeight - containerScrollTop) {
-                $(element).find('.dropdown-menu').scrollTop(activeTop - containerHeight/2);
-              }
-              $currentActive.next().addClass('active');
-            } else {
-              $currentActive.addClass('active');
-            }
-          } else if (e.keyCode === 13) {
-            // enter
-            if ($currentActive.length > 0) {
-              self.selectedDatabase(ko.dataFor($currentActive[0]));
-              self.dbSelectionVisible(false);
-              $(element).find('.dropdown-menu').scrollTop(0)
-            }
-          } else {
-            $(element).find('.dropdown-menu').scrollTop(0)
-          }
-        };
-        self.filter = ko.observable('');
-
-        self.selectedDatabase.subscribe(function () {
-          self.dbSelectionVisible(false);
-        });
-
-        self.filterEdited = ko.observable(false);
-
-        self.filter.subscribe(function () {
-          self.filterEdited(true);
-          $(element).find('.hue-inner-drop-down > .active').removeClass('.active');
-        });
-        self.dbSelectionVisible.subscribe(function (newValue) {
-          self.filterEdited(false);
-          if (newValue) {
-            window.setTimeout(function () {
-              self.filter('');
-              $(window).on('click', closeOnOutsideClick);
-              $(element).find('.db-selection-input').on('keyup', inputKeyup);
-              $(element).find('.db-selection-input').focus();
-            }, 0);
-          } else {
-            $(element).find('.hue-inner-drop-down > .active').removeClass('.active');
-            $(window).off('click', closeOnOutsideClick);
-            $(element).find('.db-selection-input').off('keyup', inputKeyup);
-          }
-        });
-        self.filteredDatabases = ko.pureComputed(function () {
-          if (self.filter() === '' || ! self.filterEdited()) {
-            return self.availableDatabases();
-          } else {
-            var lowerFilter = self.filter().toLowerCase();
-            return self.availableDatabases().filter(function (database) {
-              return database.toLowerCase().indexOf(lowerFilter) !== -1;
-            });
-          }
-        });
-      };
-
-      ko.components.register('snippet-db-selection', {
-        viewModel: {
-          createViewModel: function(params, componentInfo) {
-            return new SnippetDbSelection(params, componentInfo.element);
-          }
-        },
-        template: { element: 'snippet-db-selection-template' }
-      });
-    })();
-  </script>
-</%def>
-
 <%def name="addSnippetMenu()">
   <script type="text/html" id="add-snippet-menu-template">
     <div class="add-snippet-button" style="position:relative; width:65px; text-align: center;">