Эх сурвалжийг харах

HUE-5632 [editor] Add popularity to table details in the autocomplete dropdown

This also changes the popularity value into a percentage based on matched tables and adds database and table name to the details.
Johan Ahlen 8 жил өмнө
parent
commit
d946b54

+ 32 - 17
desktop/core/src/desktop/static/desktop/js/sqlAutocompleter3.js

@@ -504,7 +504,7 @@ var SqlAutocompleter3 = (function () {
     }
   };
 
-  Suggestions.prototype.handleTables = function (databasesDeferred, colRefDeferred) {
+  Suggestions.prototype.handleTables = function (databasesDeferred) {
     var self = this;
     var tablesDeferred = $.Deferred();
     if (self.parseResult.suggestTables) {
@@ -516,9 +516,10 @@ var SqlAutocompleter3 = (function () {
           prefix += self.parseResult.lowerCase ? 'from ' : 'FROM ';
         }
 
+        var database = suggestTables.identifierChain && suggestTables.identifierChain.length === 1 ? suggestTables.identifierChain[0].name : self.activeDatabase;
         self.apiHelper.fetchTables({
           sourceType: self.snippet.type(),
-          databaseName: suggestTables.identifierChain && suggestTables.identifierChain.length === 1 ? suggestTables.identifierChain[0].name : self.activeDatabase,
+          databaseName: database,
           successCallback: function (data) {
             var tableSuggestions = [];
             data.tables_meta.forEach(function (tableMeta) {
@@ -526,12 +527,14 @@ var SqlAutocompleter3 = (function () {
                   suggestTables.onlyViews && tableMeta.type.toLowerCase() !== 'view') {
                 return;
               }
+              var details = tableMeta;
+              details.database = database;
               tableSuggestions.push({
                 value: prefix + self.backTickIfNeeded(tableMeta.name),
                 tableName: tableMeta.name,
                 meta: AutocompleterGlobals.i18n.meta[tableMeta.type.toLowerCase()],
                 category: CATEGORIES.TABLE,
-                details: tableMeta.comment ? tableMeta : null
+                details: details
               });
             });
             self.loadingTables(false);
@@ -1278,6 +1281,13 @@ var SqlAutocompleter3 = (function () {
     return filtersDeferred;
   };
 
+  var adjustWeightsBasedOnPopularity = function(suggestions, totalPopularity) {
+    suggestions.forEach(function (suggestion) {
+      suggestion.details.popularity.relativePopularity = Math.round(100 * suggestion.details.popularity.popularity / totalPopularity);
+      suggestion.weightAdjust = suggestion.details.popularity.relativePopularity;
+    });
+  };
+
   Suggestions.prototype.handlePopularTables = function (tablesDeferred) {
     var self = this;
     var popularTablesDeferred = $.Deferred();
@@ -1299,22 +1309,24 @@ var SqlAutocompleter3 = (function () {
           });
 
           $.when(tablesDeferred).done(function (tableSuggestions) {
-            var notify = false;
+            var totalMatchedPopularity = 0;
+            var matchedSuggestions = [];
             tableSuggestions.forEach(function (suggestion) {
-              var popularity = popularityIndex[suggestion.tableName];
-              if (typeof popularity !== 'undefined') {
-                suggestion.weightAdjust = Math.min(popularity.popularity, 99); // TODO: Normalize popularity
+              var topTable = popularityIndex[suggestion.tableName];
+              if (typeof topTable !== 'undefined') {
                 suggestion.popular = true;
                 if (!suggestion.details) {
                   suggestion.details = {};
                 }
-                suggestion.details.popularity = popularity;
-                notify = true;
+                suggestion.details.popularity = topTable;
+                totalMatchedPopularity += topTable.popularity;
+                matchedSuggestions.push(suggestion);
               }
             });
             self.loadingPopularTables(false);
             popularTablesDeferred.resolve(data.top_tables);
-            if (notify) {
+            if (matchedSuggestions.length > 0) {
+              adjustWeightsBasedOnPopularity(matchedSuggestions, totalMatchedPopularity);
               self.entries.notifySubscribers();
             }
           });
@@ -1371,25 +1383,28 @@ var SqlAutocompleter3 = (function () {
           });
 
           $.when(columnsDeferred).done(function (columns) {
-            var notify = false;
+            var totalMatchedPopularity = 0;
+            var matchedSuggestions = [];
             columns.forEach(function (suggestion) {
               if (typeof suggestion.table === 'undefined') {
                 return;
               }
-              var popularity = popularityIndex[suggestion.value.toLowerCase()];
-              if (typeof popularity !== 'undefined') {
-                suggestion.weightAdjust = Math.min(popularity.columnCount, 99); // TODO: Normalize popularity
+              var topColumn = popularityIndex[suggestion.value.toLowerCase()];
+              if (typeof topColumn !== 'undefined') {
                 suggestion.popular = true;
                 if (!suggestion.details) {
                   suggestions.details = {};
                 }
-                suggestion.details.popularity = popularity;
-                notify = true;
+                topColumn.popularity = topColumn.columnCount; // No popularity for columns in response
+                suggestion.details.popularity = topColumn;
+                totalMatchedPopularity += topColumn.columnCount;
+                matchedSuggestions.push(suggestion);
               }
             });
             self.loadingPopularColumns(false);
             popularColumnsDeferred.resolve(popularColumns);
-            if (notify) {
+            if (matchedSuggestions.length > 0) {
+              adjustWeightsBasedOnPopularity(matchedSuggestions, totalMatchedPopularity);
               self.entries.notifySubscribers();
             }
           });

+ 90 - 20
desktop/libs/notebook/src/notebook/templates/hue_ace_autocompleter.mako

@@ -135,6 +135,31 @@ from desktop.views import _ko
       margin-bottom: 10px;
       font: 12px/normal 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace;direction: ltr;
     }
+
+    .popular-icon {
+      color: #EDB233;
+    }
+
+    .autocomplete-details-table .details-popularity {
+      display: inline-block;
+    }
+
+    .autocomplete-details-table .details-popularity .progress {
+      display: inline-block;
+      border-radius: 2px;
+      height: 10px;
+      width: 80px;
+    }
+
+    .autocomplete-details-table .details-popularity .progress .bar {
+      background-color: #338bb8;
+    }
+
+    .autocomplete-details-table .details-comment {
+      margin-top: 5px;
+      color: #737373;
+      font-style: italic;
+    }
   </style>
 
   <script type="text/html" id="hue-ace-autocompleter">
@@ -157,11 +182,11 @@ from desktop.views import _ko
               event: { 'mouseover': function () { $parent.hoveredIndex($index()); }, 'mouseout': function () { $parent.hoveredIndex(null); } }">
             <div class="pull-left autocompleter-dot" data-bind="style: { 'background-color': category.color }"></div>
             <div class="autocompleter-suggestion pull-left" data-bind="matchedText: { suggestion: $data, filter: $parent.suggestions.filter }"></div>
-            <div class="autocompleter-suggestion pull-right" data-bind="text: meta"></div>
+            <div class="autocompleter-suggestion pull-right"><!-- ko if: typeof popular !== 'undefined' && popular --><i class="fa fa-star-o popular-icon"></i> <!-- /ko --><span data-bind="text: meta"></span></div>
           </div>
         </div>
         <!-- ko if: focusedEntry() && focusedEntry().details -->
-        <div class="autocompleter-details" data-bind="template: { name: 'autocomplete-details-' + focusedEntry().category.detailsTemplate, data: focusedEntry }"></div>
+        <!-- ko template: { name: 'autocomplete-details-' + focusedEntry().category.detailsTemplate, data: focusedEntry } --><!-- /ko -->
         <!-- /ko -->
       </div>
     </div>
@@ -169,69 +194,114 @@ from desktop.views import _ko
   </script>
 
   <script type="text/html" id="autocomplete-details-keyword">
-    <pre data-bind="text: ko.mapping.toJSON(details)"></pre>
+    <div class="autocompleter-details">
+      <pre data-bind="text: ko.mapping.toJSON(details)"></pre>
+    </div>
   </script>
 
   <script type="text/html" id="autocomplete-details-udf">
-    <div class="details-code" data-bind="text: details.signature"></div>
-    <div data-bind="text: details.description"></div>
+    <div class="autocompleter-details">
+      <div class="details-code" data-bind="text: details.signature"></div>
+      <div data-bind="text: details.description"></div>
+    </div>
   </script>
 
   <script type="text/html" id="autocomplete-details-database">
-    <pre data-bind="text: ko.mapping.toJSON(details)"></pre>
+    <div class="autocompleter-details">
+      <pre data-bind="text: ko.mapping.toJSON(details)"></pre>
+    </div>
   </script>
 
   <script type="text/html" id="autocomplete-details-table">
-    <div class="details-header">${ _('Comment') }</div>
-    <div data-bind="text: details.comment"></div>
+    <!-- ko if: details.comment || details.popularity -->
+    <div class="autocompleter-details">
+      <div class="autocomplete-details-table">
+        <div class="details-header"><i class="fa fa-fw" data-bind="css: { 'fa-eye': details.type !== 'table', 'fa-table': details.type !== 'table' }"></i> <span data-bind="text: details.database + '.' + details.name"></span></div>
+        <!-- ko if: typeof details.popularity !== 'undefined' -->
+        <div class="details-popularity" data-bind="tooltip: { title: '${ _ko('Popularity') } ' + details.popularity.relativePopularity + '%', placement: 'bottom' }"><i class="fa fa-fw fa-star-o popular-icon"></i>
+          <div class="progress">
+            <div class="bar" data-bind="style: { 'width': details.popularity.relativePopularity + '%' }"></div>
+          </div>
+        </div>
+        <!-- /ko -->
+        <!-- ko if: typeof details.comment !== 'undefined' && details.comment !== null -->
+        <div class="details-comment" data-bind="text: details.comment"></div>
+        <!-- /ko -->
+      </div>
+    </div>
+    <!-- /ko -->
   </script>
 
   <script type="text/html" id="autocomplete-details-column">
-    <pre data-bind="text: ko.mapping.toJSON(details)"></pre>
+    <div class="autocompleter-details">
+      <pre data-bind="text: ko.mapping.toJSON(details)"></pre>
+    </div>
   </script>
 
   <script type="text/html" id="autocomplete-details-variable">
-    <pre data-bind="text: ko.mapping.toJSON(details)"></pre>
+    <div class="autocompleter-details">
+      <pre data-bind="text: ko.mapping.toJSON(details)"></pre>
+    </div>
   </script>
 
   <script type="text/html" id="autocomplete-details-hdfs">
-    <pre data-bind="text: ko.mapping.toJSON(details)"></pre>
+    <div class="autocompleter-details">
+      <pre data-bind="text: ko.mapping.toJSON(details)"></pre>
+    </div>
   </script>
 
   <script type="text/html" id="autocomplete-details-join">
-    <pre data-bind="text: ko.mapping.toJSON(details)"></pre>
+    <div class="autocompleter-details">
+      <pre data-bind="text: ko.mapping.toJSON(details)"></pre>
+    </div>
   </script>
 
   <script type="text/html" id="autocomplete-details-join-condition">
-    <pre data-bind="text: ko.mapping.toJSON(details)"></pre>
+    <div class="autocompleter-details">
+      <pre data-bind="text: ko.mapping.toJSON(details)"></pre>
+    </div>
   </script>
 
   <script type="text/html" id="autocomplete-details-agg-udf">
-    <pre data-bind="text: ko.mapping.toJSON(details)"></pre>
+    <div class="autocompleter-details">
+      <pre data-bind="text: ko.mapping.toJSON(details)"></pre>
+    </div>
   </script>
 
   <script type="text/html" id="autocomplete-details-value">
-    <pre data-bind="text: ko.mapping.toJSON(details)"></pre>
+    <div class="autocompleter-details">
+      <pre data-bind="text: ko.mapping.toJSON(details)"></pre>
+    </div>
   </script>
 
   <script type="text/html" id="autocomplete-details-identifier">
-    <pre data-bind="text: ko.mapping.toJSON(details)"></pre>
+    <div class="autocompleter-details">
+      <pre data-bind="text: ko.mapping.toJSON(details)"></pre>
+    </div>
   </script>
 
   <script type="text/html" id="autocomplete-details-cte">
-    <pre data-bind="text: ko.mapping.toJSON(details)"></pre>
+    <div class="autocompleter-details">
+      <pre data-bind="text: ko.mapping.toJSON(details)"></pre>
+    </div>
   </script>
 
   <script type="text/html" id="autocomplete-details-group-by">
-    <pre data-bind="text: ko.mapping.toJSON(details)"></pre>
+    <div class="autocompleter-details">
+      <pre data-bind="text: ko.mapping.toJSON(details)"></pre>
+    </div>
   </script>
 
   <script type="text/html" id="autocomplete-details-order-by">
-    <pre data-bind="text: ko.mapping.toJSON(details)"></pre>
+    <div class="autocompleter-details">
+      <pre data-bind="text: ko.mapping.toJSON(details)"></pre>
+    </div>
   </script>
 
   <script type="text/html" id="autocomplete-details-filter">
-    <pre data-bind="text: ko.mapping.toJSON(details)"></pre>
+    <div class="autocompleter-details">
+      <pre data-bind="text: ko.mapping.toJSON(details)"></pre>
+    </div>
   </script>