Browse Source

HUE-8570 [assist] Add distinct as an option for column samples in the context popover

This also adds controls to stop or re-run a sample query.
Johan Ahlen 7 years ago
parent
commit
693d5c1

File diff suppressed because it is too large
+ 0 - 0
desktop/core/src/desktop/static/desktop/css/hue-embedded.css


File diff suppressed because it is too large
+ 0 - 0
desktop/core/src/desktop/static/desktop/css/hue.css


File diff suppressed because it is too large
+ 0 - 0
desktop/core/src/desktop/static/desktop/css/hue3-extra.css


+ 5 - 3
desktop/core/src/desktop/static/desktop/js/apiHelper.js

@@ -1413,13 +1413,13 @@ var ApiHelper = (function () {
       }
 
       if (options.path.length > 2) {
-        url += '/stats/' + options.path.slice(2).join('/');
+        url += 'stats/' + options.path.slice(2).join('/');
       }
     }
 
     var params = {
       'format' : 'json'
-    }
+    };
 
     if (options.compute && options.compute.id) {
       params['cluster'] = options.compute.id;
@@ -1631,6 +1631,7 @@ var ApiHelper = (function () {
    * @param {string} options.sourceType
    * @param {number} [options.sampleCount] - Default 100
    * @param {string[]} options.path
+   * @param {string} [options.operation] - Default 'default'
    *
    * @return {CancellablePromise}
    */
@@ -1659,7 +1660,8 @@ var ApiHelper = (function () {
       snippet: JSON.stringify({
         type: options.sourceType
       }),
-      async: true
+      async: true,
+      operation: '"' + (options.operation || 'default') + '"'
     }, {
       silenceErrors: options.silenceErrors
     }).done(function (sampleResponse) {

+ 12 - 0
desktop/core/src/desktop/static/desktop/js/dataCatalog.js

@@ -1734,12 +1734,24 @@ var DataCatalog = (function () {
      * @param {boolean} [options.cachedOnly] - Default false
      * @param {boolean} [options.refreshCache] - Default false
      * @param {boolean} [options.cancellable] - Default false
+     * @oaram {string} [options.operation]
      *
      * @return {CancellablePromise}
      */
     DataCatalogEntry.prototype.getSample = function (options) {
       var self = this;
 
+      // This prevents caching of any non-standard sample queries, i.e. DISTINCT etc.
+      if (options && options.operation && options.operation !== 'default') {
+        return applyCancellable(ApiHelper.getInstance().fetchSample({
+          sourceType: self.dataCatalog.sourceType,
+          compute: self.compute,
+          path: self.path,
+          silenceErrors: options && options.silenceErrors,
+          operation: options.operation
+        }), options);
+      }
+
       // Check if parent has a sample that we can reuse
       if (!self.samplePromise && self.isColumn()) {
         var deferred = $.Deferred();

+ 10 - 0
desktop/core/src/desktop/static/desktop/less/components/hue-popover.less

@@ -320,6 +320,16 @@
 .context-popover-inline-autocomplete {
   height: 26px;
   margin: 0 0 10px 0;
+  .display-flex();
+
+  .context-popover-sample-filter {
+    .flex(1);
+  }
+
+  .context-popover-sample-controls {
+    .flex(0 0 120px);
+    line-height: 28px;
+  }
 
   .inline-autocomplete-container {
     height: 26px;

+ 75 - 22
desktop/core/src/desktop/templates/ko_components/ko_catalog_entries_table.mako

@@ -86,15 +86,17 @@ from desktop.views import _ko
   <script type="text/html" id="catalog-entries-list-template">
     <!-- ko if: !loading() && (!catalogEntry.isField() || catalogEntry.isComplex())-->
     <div class="context-popover-inline-autocomplete">
-      <!-- ko component: {
-        name: 'inline-autocomplete',
-        params: {
-          querySpec: querySpec,
-          facets: facets,
-          knownFacetValues: knownFacetValues,
-          autocompleteFromEntries: autocompleteFromEntries
-        }
-      } --><!-- /ko -->
+      <div class="context-popover-sample-filter">
+        <!-- ko component: {
+          name: 'inline-autocomplete',
+          params: {
+            querySpec: querySpec,
+            facets: facets,
+            knownFacetValues: knownFacetValues,
+            autocompleteFromEntries: autocompleteFromEntries
+          }
+        } --><!-- /ko -->
+      </div>
     </div>
     <!-- /ko -->
 
@@ -499,14 +501,27 @@ from desktop.views import _ko
   </script>
 
   <script type="text/html" id="field-samples-template">
-    <div class="context-popover-inline-autocomplete">
-      <!-- ko component: {
-        name: 'inline-autocomplete',
-        params: {
-          querySpec: querySpec,
-          autocompleteFromEntries: autocompleteFromEntries
-        }
-      } --><!-- /ko -->
+    <div class="context-popover-inline-autocomplete" style="display: flex">
+      <div class="context-popover-sample-filter">
+        <!-- ko component: {
+          name: 'inline-autocomplete',
+          params: {
+            querySpec: querySpec,
+            autocompleteFromEntries: autocompleteFromEntries
+          }
+        } --><!-- /ko -->
+      </div>
+      <div class="context-popover-sample-controls">
+        <div class="margin-left-10 inline-block" data-bind="component: { name: 'hue-drop-down', params: { value: operation, entries: operations } }"></div>
+        <div class="margin-left-10 inactive-action inline-block">
+          <!-- ko if: loadingSamples -->
+          <a href="javascript:void(0);" data-bind="click: cancelRunningQueries"><i class="fa fa-stop"></i></a>
+          <!-- /ko -->
+          <!-- ko ifnot: loadingSamples -->
+          <a href="javascript:void(0);" data-bind="click: function () { loadSamples(true) }"><i class="fa fa-play"></i></a>
+          <!-- /ko -->
+        </div>
+      </div>
     </div>
 
     <table class="table table-condensed table-nowrap">
@@ -515,6 +530,15 @@ from desktop.views import _ko
         <th>${ _("Sample") }</th>
       </tr>
       </thead>
+      <!-- ko if: loadingSamples -->
+      <tbody>
+      <tr>
+        <td><!-- ko hueSpinner: { spin: true, inline: true } --><!-- /ko --></td>
+      </tr>
+      </tbody>
+      <!-- /ko -->
+
+      <!-- ko ifnot: loadingSamples -->
       <tbody data-bind="foreach: filteredColumnSamples">
       <tr>
         <td class="sample-column" data-bind="html: $data, attr: { 'title': hueUtils.html2text($data) }"></td>
@@ -532,6 +556,7 @@ from desktop.views import _ko
       </tr>
       </tbody>
       <!-- /ko -->
+      <!-- /ko -->
     </table>
   </script>
 
@@ -544,7 +569,23 @@ from desktop.views import _ko
         self.querySpec = ko.observable();
 
         self.hasErrors = ko.observable();
-        self.loading = ko.observable();
+        self.loadingSamples = ko.observable();
+
+        self.operations = [
+          {
+            label: '${ _("default") }',
+            type: 'default'
+          },{
+            label: '${ _("distinct") }',
+            type: 'distinct'
+          }
+        ];
+
+        self.operation = ko.observable(self.operations[0]);
+
+        self.operation.subscribe(function () {
+          self.loadSamples();
+        });
 
         self.columnSamples = ko.observableArray();
 
@@ -575,18 +616,25 @@ from desktop.views import _ko
           return result;
         };
 
-        self.cancellablePromises.push(self.catalogEntry.getSample({ silenceErrors: true, cancellable: true }).done(function (samples) {
+        self.loadSamples();
+      }
+
+      FieldSamples.prototype.loadSamples = function (refreshCache) {
+        var self = this;
+        self.cancelRunningQueries();
+        self.loadingSamples(true);
+        self.cancellablePromises.push(self.catalogEntry.getSample({ silenceErrors: true, cancellable: true, refreshCache: refreshCache, operation: self.operation().type }).done(function (samples) {
           if (samples.data && samples.data.length) {
             self.columnSamples(samples.data);
           }
         }).fail(function () {
           self.hasErrors(true);
         }).always(function () {
-          self.loading(false);
+          self.loadingSamples(false);
         }));
-      }
+      };
 
-      FieldSamples.prototype.dispose = function () {
+      FieldSamples.prototype.cancelRunningQueries = function () {
         var self = this;
         while (self.cancellablePromises.length) {
           var promise = self.cancellablePromises.pop();
@@ -596,6 +644,11 @@ from desktop.views import _ko
         }
       };
 
+      FieldSamples.prototype.dispose = function () {
+        var self = this;
+        self.cancelRunningQueries();
+      };
+
       ko.components.register('field-samples', {
         viewModel: FieldSamples,
         template: { element: 'field-samples-template' }

Some files were not shown because too many files changed in this diff