ソースを参照

HUE-7362 [assist] Use the new inline autocomplete input for assist filters

With this the inline autocomplete component is used for SQL and Collections assist. It only has facets for sql views and tables at this point.
Johan Ahlen 8 年 前
コミット
522583959a

ファイルの差分が大きいため隠しています
+ 0 - 0
desktop/core/src/desktop/static/desktop/css/hue.css


ファイルの差分が大きいため隠しています
+ 0 - 0
desktop/core/src/desktop/static/desktop/css/hue3-extra.css


+ 20 - 3
desktop/core/src/desktop/static/desktop/js/assist/assistDbEntry.js

@@ -28,7 +28,7 @@ var AssistDbEntry = (function () {
    * @param {AssistDbEntry} parent
    * @param {AssistDbEntry} parent
    * @param {AssistDbSource} assistDbSource
    * @param {AssistDbSource} assistDbSource
    * @param {Object} filter
    * @param {Object} filter
-   * @param {function} filter.query (observable)
+   * @param {function} filter.querySpec (observable)
    * @param {function} filter.showViews (observable)
    * @param {function} filter.showViews (observable)
    * @param {function} filter.showTables (observable)
    * @param {function} filter.showTables (observable)
    * @param {Object} i18n
    * @param {Object} i18n
@@ -78,15 +78,32 @@ var AssistDbEntry = (function () {
     });
     });
 
 
     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.showViews() && (!self.filter.querySpec().facets || self.filter.querySpec().facets === {}) && (!self.filter.querySpec().text || self.filter.querySpec().text.length === 0))) {
         return self.entries();
         return self.entries();
       }
       }
+
       var result = [];
       var result = [];
       $.each(self.entries(), function (index, entry) {
       $.each(self.entries(), function (index, entry) {
         if ((entry.definition.isTable && !self.filter.showTables()) || (entry.definition.isView && !self.filter.showViews()) ) {
         if ((entry.definition.isTable && !self.filter.showTables()) || (entry.definition.isView && !self.filter.showViews()) ) {
           return;
           return;
         }
         }
-        if (entry.definition.name.toLowerCase().indexOf(self.filter.query().toLowerCase()) > -1) {
+        var facets = self.filter.querySpec().facets;
+        var facetMatch = !facets || !facets['type'];
+        if (!facetMatch) {
+          facets['type'].every(function (typeFacet) {
+            facetMatch = (typeFacet === 'table' && entry.definition.isTable) || (typeFacet === 'view' && entry.definition.isView);
+            return !facetMatch;
+          });
+        }
+        var textMatch = !self.filter.querySpec().text || self.filter.querySpec().text.length === 0;
+        if (!textMatch) {
+          var nameLower = entry.definition.name.toLowerCase();
+          self.filter.querySpec().text.every(function (text) {
+            textMatch = nameLower.indexOf(text.toLowerCase()) !== -1;
+            return !textMatch;
+          });
+        }
+        if (facetMatch && textMatch) {
           result.push(entry);
           result.push(entry);
         }
         }
       });
       });

+ 5 - 5
desktop/core/src/desktop/static/desktop/js/assist/assistDbSource.js

@@ -73,11 +73,11 @@ var AssistDbSource = (function () {
     });
     });
 
 
     self.filter = {
     self.filter = {
-      query: ko.observable("").extend({ rateLimit: 150 })
+      querySpec: ko.observable({})
     };
     };
 
 
     self.filterActive = ko.pureComputed(function () {
     self.filterActive = ko.pureComputed(function () {
-      return self.filter.query().length !== 0;
+      return self.filter.querySpec() && self.filter.querySpec().query !== '';
     });
     });
 
 
     var storageSearchVisible = $.totalStorage(self.sourceType + ".assist.searchVisible");
     var storageSearchVisible = $.totalStorage(self.sourceType + ".assist.searchVisible");
@@ -94,12 +94,12 @@ var AssistDbSource = (function () {
     });
     });
 
 
     self.filteredEntries = ko.pureComputed(function () {
     self.filteredEntries = ko.pureComputed(function () {
-      if (self.filter.query().length === 0) {
+      if (!self.filter.querySpec() || typeof self.filter.querySpec().query === 'undefined' || !self.filter.querySpec().query) {
         return self.databases();
         return self.databases();
       }
       }
       var result = [];
       var result = [];
       $.each(self.databases(), function (index, database) {
       $.each(self.databases(), function (index, database) {
-        if (database.definition.name.toLowerCase().indexOf(self.filter.query().toLowerCase()) > -1) {
+        if (database.definition.name.toLowerCase().indexOf(self.filter.querySpec().query.toLowerCase()) > -1) {
           result.push(database);
           result.push(database);
         }
         }
       });
       });
@@ -184,7 +184,7 @@ var AssistDbSource = (function () {
     self.loading = ko.observable(false);
     self.loading = ko.observable(false);
     var dbIndex = {};
     var dbIndex = {};
     var nestedFilter = {
     var nestedFilter = {
-      query: ko.observable("").extend({ rateLimit: { timeout: 250, method: 'notifyWhenChangesStop' } }),
+      querySpec: ko.observable({}),
       showTables: ko.observable(true),
       showTables: ko.observable(true),
       showViews: ko.observable(true),
       showViews: ko.observable(true),
       activeEditorTables: ko.observableArray([])
       activeEditorTables: ko.observableArray([])

+ 4 - 0
desktop/core/src/desktop/static/desktop/less/hue-assist.less

@@ -557,6 +557,10 @@
   margin-right: 8px;
   margin-right: 8px;
 }
 }
 
 
+.assist-filter .inline-autocomplete-container {
+  height: 25px;
+}
+
 .assist-filter input {
 .assist-filter input {
   -webkit-box-sizing: border-box;
   -webkit-box-sizing: border-box;
   -moz-box-sizing: border-box;
   -moz-box-sizing: border-box;

+ 5 - 1
desktop/core/src/desktop/static/desktop/less/hue.less

@@ -320,6 +320,10 @@ body {
   margin-top: 5px;
   margin-top: 5px;
   height: 30px;
   height: 30px;
   width: 100%;
   width: 100%;
+
+  > div {
+    right: 10px !important;
+  }
 }
 }
 
 
 .inline-autocomplete-container {
 .inline-autocomplete-container {
@@ -330,7 +334,7 @@ body {
   > div {
   > div {
     position:absolute;
     position:absolute;
     left: 0;
     left: 0;
-    right: 10px;
+    right: 0;
     height: 30px;
     height: 30px;
 
 
     input {
     input {

+ 50 - 14
desktop/core/src/desktop/templates/assist.mako

@@ -874,7 +874,16 @@ from notebook.conf import ENABLE_QUERY_BUILDER, ENABLE_QUERY_SCHEDULING, get_ord
       </div>
       </div>
     </div>
     </div>
     <div class="assist-flex-search" data-bind="visible: hasEntries() && ! hasErrors()">
     <div class="assist-flex-search" data-bind="visible: hasEntries() && ! hasErrors()">
-      <div class="assist-filter"><input class="clearable" type="text" placeholder="${ _('Filter...') }" data-bind="clearable: filter.query, value: filter.query, valueUpdate: 'afterkeydown'"/></div>
+      <div class="assist-filter">
+        <!-- ko component: {
+            name: 'inline-autocomplete',
+            params: {
+              querySpec: filter.querySpec,
+              facets: [],
+              knownFacetValues: {}
+            }
+          } --><!-- /ko -->
+      </div>
     </div>
     </div>
     <div class="assist-flex-fill assist-db-scrollable" data-bind="visible: ! hasErrors() && ! loading() && hasEntries()">
     <div class="assist-flex-fill assist-db-scrollable" data-bind="visible: ! hasErrors() && ! loading() && hasEntries()">
       <!-- ko if: ! loading() && filteredEntries().length == 0 -->
       <!-- ko if: ! loading() && filteredEntries().length == 0 -->
@@ -942,7 +951,16 @@ from notebook.conf import ENABLE_QUERY_BUILDER, ENABLE_QUERY_SCHEDULING, get_ord
       <!-- /ko -->
       <!-- /ko -->
     </div>
     </div>
     <div class="assist-flex-search" data-bind="visible: hasEntries() && !$parent.loading() && !$parent.hasErrors()">
     <div class="assist-flex-search" data-bind="visible: hasEntries() && !$parent.loading() && !$parent.hasErrors()">
-      <div class="assist-filter"><input class="clearable" type="text" placeholder="${ _('Filter...') }" data-bind="clearable: filter.query, value: filter.query, valueUpdate: 'afterkeydown'"/></div>
+      <div class="assist-filter">
+        <!-- ko component: {
+          name: 'inline-autocomplete',
+          params: {
+            querySpec: filter.querySpec,
+            facets: ['type'],
+            knownFacetValues: { 'type': {'table': -1, 'view': -1 } }
+          }
+        } --><!-- /ko -->
+      </div>
     </div>
     </div>
     <div class="assist-flex-fill assist-db-scrollable" data-bind="visible: ! hasErrors() && ! loading()">
     <div class="assist-flex-fill assist-db-scrollable" data-bind="visible: ! hasErrors() && ! loading()">
       <!-- ko template: 'assist-db-entries' --><!-- /ko -->
       <!-- ko template: 'assist-db-entries' --><!-- /ko -->
@@ -2211,13 +2229,22 @@ from notebook.conf import ENABLE_QUERY_BUILDER, ENABLE_QUERY_SCHEDULING, get_ord
           </div>
           </div>
         </div>
         </div>
         <div class="assist-flex-search" data-bind="visible: activeTables().length > 0">
         <div class="assist-flex-search" data-bind="visible: activeTables().length > 0">
-          <div class="assist-filter"><input class="clearable" type="text" data-bind="clearable: filter.query, value: filter.query, valueUpdate: 'afterkeydown'" placeholder="${ _('Filter...') }" /></div>
+          <div class="assist-filter">
+            <!-- ko component: {
+              name: 'inline-autocomplete',
+              params: {
+                querySpec: filter.querySpec,
+                facets: ['type'],
+                knownFacetValues: { 'type': {'table': -1, 'view': -1, 'column': -1, 'string': -1 } }
+              }
+            } --><!-- /ko -->
+          </div>
         </div>
         </div>
         <div class="assist-flex-half assist-db-scrollable">
         <div class="assist-flex-half assist-db-scrollable">
-          <!-- ko if: filteredTables().length === 0 && filter.query() === '' -->
+          <!-- ko if: filteredTables().length === 0 && (!filter.querySpec() || filter.querySpec().query === '') -->
           <div class="assist-no-entries">${ _('No tables identified.') }</div>
           <div class="assist-no-entries">${ _('No tables identified.') }</div>
           <!-- /ko -->
           <!-- /ko -->
-          <!-- ko if: filteredTables().length === 0 && filter.query() !== '' -->
+          <!-- ko if: filteredTables().length === 0 && filter.querySpec() && filter.querySpec().query !== '' -->
           <div class="assist-no-entries">${ _('No entries found.') }</div>
           <div class="assist-no-entries">${ _('No entries found.') }</div>
           <!-- /ko -->
           <!-- /ko -->
           <!-- ko if: filteredTables().length > 0 -->
           <!-- ko if: filteredTables().length > 0 -->
@@ -2325,7 +2352,7 @@ from notebook.conf import ENABLE_QUERY_BUILDER, ENABLE_QUERY_SCHEDULING, get_ord
         var activeTableIndex = {};
         var activeTableIndex = {};
 
 
         self.filter = {
         self.filter = {
-          query: ko.observable(''),
+          querySpec: ko.observable({}),
           showViews: ko.observable(true),
           showViews: ko.observable(true),
           showTables: ko.observable(true)
           showTables: ko.observable(true)
         };
         };
@@ -2333,7 +2360,7 @@ from notebook.conf import ENABLE_QUERY_BUILDER, ENABLE_QUERY_SCHEDULING, get_ord
         var openedByFilter = [];
         var openedByFilter = [];
 
 
         self.filteredTables = ko.pureComputed(function () {
         self.filteredTables = ko.pureComputed(function () {
-          if (self.filter.query() === '') {
+          if (!self.filter.querySpec() || self.filter.querySpec().query === '') {
             while (openedByFilter.length) {
             while (openedByFilter.length) {
               openedByFilter.pop().open(false);
               openedByFilter.pop().open(false);
             }
             }
@@ -2346,7 +2373,7 @@ from notebook.conf import ENABLE_QUERY_BUILDER, ENABLE_QUERY_SCHEDULING, get_ord
                 openedByFilter.push(table);
                 openedByFilter.push(table);
               }
               }
               return true;
               return true;
-            } else if (table.definition.name.toLowerCase().indexOf(self.filter.query().toLowerCase()) > -1) {
+            } else if (self.filter.querySpec() && table.definition.name.toLowerCase().indexOf(self.filter.querySpec().query.toLowerCase()) > -1) {
               return true;
               return true;
             }
             }
             return false;
             return false;
@@ -2654,13 +2681,22 @@ from notebook.conf import ENABLE_QUERY_BUILDER, ENABLE_QUERY_SCHEDULING, get_ord
           </div>
           </div>
         </div>
         </div>
         <div class="assist-flex-search" data-bind="visible: activeCollection() && activeCollection().fields().length > 0">
         <div class="assist-flex-search" data-bind="visible: activeCollection() && activeCollection().fields().length > 0">
-          <div class="assist-filter"><input class="clearable" type="text" data-bind="clearable: filter.query, value: filter.query, valueUpdate: 'afterkeydown'" placeholder="${ _('Filter...') }" /></div>
+          <div class="assist-filter">
+            <!-- ko component: {
+              name: 'inline-autocomplete',
+              params: {
+                querySpec: filter.querySpec,
+                facets: [],
+                knownFacetValues: {}
+              }
+            } --><!-- /ko -->
+          </div>
         </div>
         </div>
         <div class="assist-flex-half assist-db-scrollable">
         <div class="assist-flex-half assist-db-scrollable">
-          <!-- ko if: filteredFields().length === 0 && filter.query() === '' -->
+          <!-- ko if: filteredFields().length === 0 && (!filter.querySpec() || filter.querySpec().query === '') -->
           <div class="assist-no-entries">${ _('No fields available.') }</div>
           <div class="assist-no-entries">${ _('No fields available.') }</div>
           <!-- /ko -->
           <!-- /ko -->
-          <!-- ko if: filteredFields().length === 0 && filter.query() !== '' -->
+          <!-- ko if: filteredFields().length === 0 && filter.querySpec() && filter.querySpec().query !== '' -->
           <div class="assist-no-entries">${ _('No fields found.') }</div>
           <div class="assist-no-entries">${ _('No fields found.') }</div>
           <!-- /ko -->
           <!-- /ko -->
           <!-- ko if: filteredFields().length > 0 -->
           <!-- ko if: filteredFields().length > 0 -->
@@ -2686,7 +2722,7 @@ from notebook.conf import ENABLE_QUERY_BUILDER, ENABLE_QUERY_SCHEDULING, get_ord
         self.activeCollection = ko.observable();
         self.activeCollection = ko.observable();
 
 
         self.filter = {
         self.filter = {
-          query: ko.observable('')
+          querySpec: ko.observable({})
         };
         };
 
 
         var activeDashboardCollection = huePubSub.subscribe('set.active.dashboard.collection', function(collection) {
         var activeDashboardCollection = huePubSub.subscribe('set.active.dashboard.collection', function(collection) {
@@ -2697,11 +2733,11 @@ from notebook.conf import ENABLE_QUERY_BUILDER, ENABLE_QUERY_SCHEDULING, get_ord
           if (!self.activeCollection()){
           if (!self.activeCollection()){
             return [];
             return [];
           }
           }
-          if (self.filter.query() === '') {
+          if (!self.filter.querySpec() || self.filter.querySpec().query === '') {
             return self.activeCollection().fields();
             return self.activeCollection().fields();
           }
           }
           var result = self.activeCollection().fields().filter(function (field) {
           var result = self.activeCollection().fields().filter(function (field) {
-            if (field.name().toLowerCase().indexOf(self.filter.query().toLowerCase()) > -1) {
+            if (field.name().toLowerCase().indexOf(self.filter.querySpec().query.toLowerCase()) > -1) {
               return true;
               return true;
             }
             }
             return false;
             return false;

+ 37 - 13
desktop/core/src/desktop/templates/ko_components.mako

@@ -660,18 +660,25 @@ from desktop.views import _ko
 
 
       var InlineAutocomplete = function (params) {
       var InlineAutocomplete = function (params) {
         var self = this;
         var self = this;
-        self.placeHolder = params.placeHolder;
+        self.disposals = [];
+
+        self.placeHolder = params.placeHolder || '${ _('Filter...') }';
         self.hasFocus = params.hasFocus || ko.observable();
         self.hasFocus = params.hasFocus || ko.observable();
-        self.searchInput = ko.observable('');
         self.querySpec = params.querySpec;
         self.querySpec = params.querySpec;
+        self.autocompleteFromEntries = params.autocompleteFromEntries || function () {};
+        self.facets = params.facets || [];
+        self.knownFacetValues = params.knownFacetValues || {};
+
+        self.searchInput = ko.observable('');
         self.inlineAutocomplete = ko.observable('');
         self.inlineAutocomplete = ko.observable('');
         self.lastNonPartial = null;
         self.lastNonPartial = null;
         self.lastResult = {};
         self.lastResult = {};
-        self.autocompleteFromEntries = params.autocompleteFromEntries;
-        self.disposals = [];
 
 
-        self.facets = params.facets;
-        self.knownFacetValues = params.knownFacetValues;
+        self.querySpec({
+          query: '',
+          facets: {},
+          text: []
+        });
 
 
         self.onClear = function () {
         self.onClear = function () {
           if (params.onClear) {
           if (params.onClear) {
@@ -695,11 +702,17 @@ from desktop.views import _ko
           }
           }
           if (newValue !== '') {
           if (newValue !== '') {
             self.triggerAutocomplete(newValue);
             self.triggerAutocomplete(newValue);
+          } else {
+            self.querySpec({
+              query: '',
+              facets: {},
+              text: []
+            })
           }
           }
         });
         });
 
 
         self.disposals.push(function () {
         self.disposals.push(function () {
-          inputSub.remove();
+          inputSub.dispose();
         });
         });
 
 
         var onKeyDown = function (event) {
         var onKeyDown = function (event) {
@@ -738,7 +751,7 @@ from desktop.views import _ko
         });
         });
 
 
         self.disposals.push(function () {
         self.disposals.push(function () {
-          focusSub.remove();
+          focusSub.dispose();
         });
         });
       };
       };
 
 
@@ -781,8 +794,9 @@ from desktop.views import _ko
         }
         }
 
 
         if (self.lastResult.suggestFacetValues && !newAutocomplete) {
         if (self.lastResult.suggestFacetValues && !newAutocomplete) {
-          if (self.knownFacetValues()[self.lastResult.suggestFacetValues.toLowerCase()]) {
-            Object.keys(self.knownFacetValues()[self.lastResult.suggestFacetValues.toLowerCase()]).every(function (value) {
+          var facetValues = ko.unwrap(self.knownFacetValues);
+          if (facetValues[self.lastResult.suggestFacetValues.toLowerCase()]) {
+            Object.keys(facetValues[self.lastResult.suggestFacetValues.toLowerCase()]).every(function (value) {
               if (value.toLowerCase().indexOf(partialLower) === 0) {
               if (value.toLowerCase().indexOf(partialLower) === 0) {
                 newAutocomplete = self.lastNonPartial + partial + value.substring(partial.length, value.length);
                 newAutocomplete = self.lastNonPartial + partial + value.substring(partial.length, value.length);
                 return false;
                 return false;
@@ -819,6 +833,15 @@ from desktop.views import _ko
 
 
         if (self.lastNonPartial && self.lastNonPartial === nonPartial) {
         if (self.lastNonPartial && self.lastNonPartial === nonPartial) {
           self.updateInlineAutocomplete(partial);
           self.updateInlineAutocomplete(partial);
+          self.lastResult = globalSearchParser.parseGlobalSearch(newValue, '');
+          var querySpec = { query: newValue };
+          if (self.lastResult.facets) {
+            querySpec.facets = self.lastResult.facets
+          }
+          if (self.lastResult.text) {
+            querySpec.text = self.lastResult.text;
+          }
+          self.querySpec(querySpec);
           return;
           return;
         }
         }
 
 
@@ -1127,12 +1150,13 @@ from desktop.views import _ko
 
 
         navPromise.done(function (data) {
         navPromise.done(function (data) {
           if (data.facets) {
           if (data.facets) {
+            var facetValues = ko.unwrap(self.knownFacetValues);
             Object.keys(data.facets).forEach(function (facet) {
             Object.keys(data.facets).forEach(function (facet) {
-              if (!self.knownFacetValues()[facet] && Object.keys(data.facets[facet]).length > 0) {
-                self.knownFacetValues()[facet] = {};
+              if (!facetValues[facet] && Object.keys(data.facets[facet]).length > 0) {
+                facetValues[facet] = {};
               }
               }
               Object.keys(data.facets[facet]).forEach(function (facetKey) {
               Object.keys(data.facets[facet]).forEach(function (facetKey) {
-                self.knownFacetValues()[facet][facetKey] = data.facets[facet][facetKey];
+                facetValues[facet][facetKey] = data.facets[facet][facetKey];
               });
               });
             })
             })
           }
           }

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません