瀏覽代碼

HUE-7766 [search] Add query facet filter to counter widgets

Romain Rigaux 8 年之前
父節點
當前提交
faeb234

+ 2 - 1
desktop/libs/dashboard/src/dashboard/api.py

@@ -35,7 +35,7 @@ from dashboard.data_export import download as export_download
 from dashboard.decorators import allow_viewer_only
 from dashboard.decorators import allow_viewer_only
 from dashboard.facet_builder import _guess_gap, _zoom_range_facet, _new_range_facet
 from dashboard.facet_builder import _guess_gap, _zoom_range_facet, _new_range_facet
 from dashboard.models import Collection2, augment_solr_response, pairwise2, augment_solr_exception,\
 from dashboard.models import Collection2, augment_solr_response, pairwise2, augment_solr_exception,\
-  NESTED_FACET_FORM, COMPARE_FACET
+  NESTED_FACET_FORM, COMPARE_FACET, QUERY_FACET
 
 
 
 
 LOG = logging.getLogger(__name__)
 LOG = logging.getLogger(__name__)
@@ -429,6 +429,7 @@ def _create_facet(collection, user, facet_id, facet_label, facet_field, widget_t
       properties['facets'] = [facet]
       properties['facets'] = [facet]
       properties['domain'] = {'blockParent': [], 'blockChildren': []}
       properties['domain'] = {'blockParent': [], 'blockChildren': []}
       properties['compare'] = COMPARE_FACET
       properties['compare'] = COMPARE_FACET
+      properties['filter'] = QUERY_FACET
 
 
       if widget_type == 'hit-widget':
       if widget_type == 'hit-widget':
         facet_type = 'function'
         facet_type = 'function'

+ 20 - 14
desktop/libs/dashboard/src/dashboard/models.py

@@ -14,6 +14,7 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # See the License for the specific language governing permissions and
 # limitations under the License.
 # limitations under the License.
+
 from __future__ import division
 from __future__ import division
 
 
 import collections
 import collections
@@ -45,7 +46,8 @@ NESTED_FACET_FORM = {
     'isDate': False,
     'isDate': False,
     'aggregate': {'function': 'unique', 'formula': '', 'plain_formula': '', 'percentile': 50}
     'aggregate': {'function': 'unique', 'formula': '', 'plain_formula': '', 'percentile': 50}
 }
 }
-COMPARE_FACET = {'is_enabled': False, 'gap': '1WEEK', 'use_percentage': False, 'cohort_number': 1}
+COMPARE_FACET = {'is_enabled': False, 'gap': '7DAYS', 'use_percentage': False, 'show_both': False, 'cohort_number': 1}
+QUERY_FACET = {'is_enabled': False, 'query': ''}
 
 
 
 
 class Collection2(object):
 class Collection2(object):
@@ -149,6 +151,8 @@ class Collection2(object):
 
 
       if 'compare' not in properties:
       if 'compare' not in properties:
         properties['compare'] = COMPARE_FACET
         properties['compare'] = COMPARE_FACET
+      if 'filter' not in properties:
+        properties['filter'] = QUERY_FACET
 
 
     if 'qdefinitions' not in props['collection']:
     if 'qdefinitions' not in props['collection']:
       props['collection']['qdefinitions'] = []
       props['collection']['qdefinitions'] = []
@@ -487,27 +491,29 @@ def augment_solr_response(response, collection, query):
       if category == 'function' and name in response['facets']:
       if category == 'function' and name in response['facets']:
         collection_facet = get_facet_field(category, name, collection['facets'])
         collection_facet = get_facet_field(category, name, collection['facets'])
 
 
+        value = response['facets'][name]
+        counts = {'value': value, 'percentage': 0}
+
+        if collection_facet['properties']['filter']['is_enabled']:
+          if collection_facet['properties']['compare']['is_enabled']:
+            value = value[name]
+          else:
+            counts['value'] = value['count']
+
         if collection_facet['properties']['compare']['is_enabled']:
         if collection_facet['properties']['compare']['is_enabled']:
-          orignal_number, final_number = response['facets'][name]['buckets'][0].get(name), response['facets'][name]['buckets'][1].get(name)
-          if orignal_number is None or final_number is None:
-            value = 0
-          elif collection_facet['properties']['compare']['use_percentage']:
+          orignal_number, final_number = value['buckets'][0].get(name, 0), value['buckets'][1].get(name, 0)
+          if collection_facet['properties']['compare']['use_percentage']:
             if orignal_number != 0:
             if orignal_number != 0:
-              value = (final_number - orignal_number) / orignal_number * 100.0
-            else:
-              value = 0 
-          else:
-            value = final_number - orignal_number
-        else:
-          value = response['facets'][name]['count']
-#           value = response['facets'][name]
+              counts['percentage'] = (final_number - orignal_number) / orignal_number * 100.0
+
+          counts['value'] = final_number - orignal_number
 
 
         facet = {
         facet = {
           'id': collection_facet['id'],
           'id': collection_facet['id'],
           'query': name,
           'query': name,
           'type': category,
           'type': category,
           'label': name,
           'label': name,
-          'counts': value,
+          'counts': counts,
         }
         }
         normalized_facets.append(facet)
         normalized_facets.append(facet)
       elif category == 'nested' and name in response['facets']:
       elif category == 'nested' and name in response['facets']:

+ 3 - 0
desktop/libs/dashboard/src/dashboard/static/dashboard/js/search.ko.js

@@ -752,6 +752,9 @@ var Collection = function (vm, collection) {
       facet.properties.compare.use_percentage.subscribe(function () {
       facet.properties.compare.use_percentage.subscribe(function () {
         vm.search();
         vm.search();
       });
       });
+      facet.properties.compare.gap.subscribe(function () {
+        vm.search();
+      });
      }
      }
 
 
     // For Solr 5+  only
     // For Solr 5+  only

+ 42 - 12
desktop/libs/dashboard/src/dashboard/templates/common_search.mako

@@ -2011,7 +2011,10 @@ ${ dashboard.layout_skeleton(suffix='search') }
     <div data-bind="with: $root.collection.getFacetById($parent.id())">
     <div data-bind="with: $root.collection.getFacetById($parent.id())">
       <span data-bind="template: { name: 'facet-toggle2' }"></span>
       <span data-bind="template: { name: 'facet-toggle2' }"></span>
 
 
-      <span class="pull-right" data-bind="visible: $root.availableDateFields().length > 0, template: { name: 'facet-compare', data: properties.compare }"></span>
+      <div class="pull-right">
+        <span data-bind="visible: $root.collection.supportAnalytics(), template: { name: 'facet-filter', data: properties.filter }"></span>
+        <span data-bind="visible: $root.collection.supportAnalytics() && $root.availableDateFields().length > 0, template: { name: 'facet-compare', data: properties.compare }"></span>
+      </div>
     </div>
     </div>
 
 
     <span class="big-counter" data-bind="template: { name: 'counter-form', data: {counts: counts(), properties: $root.collection.getFacetById($parent.id()).properties }}"></span>
     <span class="big-counter" data-bind="template: { name: 'counter-form', data: {counts: counts(), properties: $root.collection.getFacetById($parent.id()).properties }}"></span>
@@ -2020,19 +2023,46 @@ ${ dashboard.layout_skeleton(suffix='search') }
 </script>
 </script>
 
 
 
 
+<script type="text/html" id="facet-filter">
+  <label>
+    <input type="checkbox" data-bind="checked: is_enabled"/> ${ _('Filter') }
+  </label>
+
+  <!-- ko if: is_enabled -->
+  <div class="facet-field-cnt">
+    <span class="spinedit-cnt">
+      <span class="facet-field-label">
+        ${ _('Query') }
+      </span>
+      <div data-bind="component: { name: 'hue-simple-ace-editor', params: {
+        value: query,
+        onExec: $parent.searchBtn,
+        placeHolder: $root.collection.engine() === 'solr' ? '${ _ko('Example: field:value, or press CTRL + space') }' : '${ _ko('Example: col = value, or press CTRL + space') }',
+        autocomplete: { type: $root.collection.engine() + 'Query', support: { collection: $root.collection } },
+        mode: $root.collection.engine(),
+        singleLine: true }
+      }"></div>
+    </span>
+  </div>
+  <!-- /ko -->
+</script>
+
+
 <script type="text/html" id="counter-form">
 <script type="text/html" id="counter-form">
   <i class="fa" data-bind="visible: properties.compare.is_enabled, css: { 'fa-caret-down': counts < 0, 'fa-caret-up': counts > 0 }"></i>
   <i class="fa" data-bind="visible: properties.compare.is_enabled, css: { 'fa-caret-down': counts < 0, 'fa-caret-up': counts > 0 }"></i>
 
 
-  <span  data-bind="textSqueezer: counts"></span>
+  <span data-bind="textSqueezer: counts.value, visible: !properties.compare.use_percentage() || properties.compare.show_both()"></span>
 
 
-  <span  data-bind="visible: properties.compare.use_percentage">
-    ${ '%' }
+  <span data-bind="visible: properties.compare.use_percentage">
+    <span data-bind="textSqueezer: counts.percentage"></span> ${ '%' }
   </span>
   </span>
 </script>
 </script>
 
 
 
 
 <script type="text/html" id="facet-compare">
 <script type="text/html" id="facet-compare">
-  <input type="checkbox" data-bind="checked: is_enabled"/> ${ _('Compare') }
+  <label>
+    <input type="checkbox" data-bind="checked: is_enabled"/> ${ _('Compare') }
+  </label>
 
 
   <!-- ko if: is_enabled -->
   <!-- ko if: is_enabled -->
   <div class="facet-field-cnt">
   <div class="facet-field-cnt">
@@ -2040,8 +2070,8 @@ ${ dashboard.layout_skeleton(suffix='search') }
       <span class="facet-field-label">
       <span class="facet-field-label">
         ${ _('Cohorts') }
         ${ _('Cohorts') }
       </span>
       </span>
-      <input type="text" class="input-medium"/>
-      <input type="number" class="input-medium"/>
+      <span data-bind="template: {name: 'time-filter-select', data: {gap: gap} }"></span>
+      ## <input type="number" class="input-xsmall" data-bind="value: cohort_number"/>
     </span>
     </span>
   </div>
   </div>
 
 
@@ -2055,9 +2085,9 @@ ${ dashboard.layout_skeleton(suffix='search') }
       </label>
       </label>
       <label>
       <label>
         <span class="facet-field-label">
         <span class="facet-field-label">
-          ${ _('Hide value') }
+          ${ _('Both values') }
         </span>
         </span>
-        <input type="checkbox"/>
+        <input type="checkbox" data-bind="checked: show_both, enable: use_percentage"/>
       </label>
       </label>
     </span>
     </span>
   </div>
   </div>
@@ -2656,7 +2686,7 @@ ${ dashboard.layout_skeleton(suffix='search') }
 
 
 <script type="text/html" id="time-filter">
 <script type="text/html" id="time-filter">
   <span data-bind="visible: $root.availableDateFields().length > 0" >
   <span data-bind="visible: $root.availableDateFields().length > 0" >
-    <span data-bind="template: {name: 'time-filter-select'}"></span>
+    <span data-bind="template: {name: 'time-filter-select', data: {gap: collection.timeFilter.value} }"></span>
     <a class="btn pointer" title="${ _('Time Settings') }" rel="tooltip" data-placement="bottom" data-toggle="modal" data-target="#timeSettingsDemiModal">
     <a class="btn pointer" title="${ _('Time Settings') }" rel="tooltip" data-placement="bottom" data-toggle="modal" data-target="#timeSettingsDemiModal">
       <i class="fa fa-calendar"></i>
       <i class="fa fa-calendar"></i>
     </a>
     </a>
@@ -2675,7 +2705,7 @@ ${ dashboard.layout_skeleton(suffix='search') }
 
 
 
 
 <script type="text/html" id="time-filter-select">
 <script type="text/html" id="time-filter-select">
-  <select id="settingstimeinterval" data-bind="value: collection.timeFilter.value" class="input-small" style="margin-right: 4px">
+  <select id="settingstimeinterval" data-bind="value: $data.gap" class="input-small" style="margin-right: 4px">
     <option value="all">${ _('All') }</option>
     <option value="all">${ _('All') }</option>
     <option value="5MINUTES">${ _('Past 5 Minutes') }</option>
     <option value="5MINUTES">${ _('Past 5 Minutes') }</option>
     <option value="30MINUTES">${ _('Past 30 Minutes') }</option>
     <option value="30MINUTES">${ _('Past 30 Minutes') }</option>
@@ -2719,7 +2749,7 @@ ${ dashboard.layout_skeleton(suffix='search') }
               <div class="control-group" data-bind="visible: collection.timeFilter.type() == 'rolling'">
               <div class="control-group" data-bind="visible: collection.timeFilter.type() == 'rolling'">
                 <label class="control-label" for="settingstimeinterval">${ _('Interval') }</label>
                 <label class="control-label" for="settingstimeinterval">${ _('Interval') }</label>
                 <div class="controls">
                 <div class="controls">
-                  <span data-bind="template: {name: 'time-filter-select'}"></span>
+                  <span data-bind="template: {name: 'time-filter-select', data: { gap: collection.timeFilter.value} }"></span>
                 </div>
                 </div>
               </div>
               </div>
               <div class="control-group" data-bind="visible: collection.timeFilter.type() == 'fixed'">
               <div class="control-group" data-bind="visible: collection.timeFilter.type() == 'fixed'">

+ 11 - 11
desktop/libs/libsolr/src/libsolr/api.py

@@ -177,24 +177,24 @@ class SolrApi(object):
             json_facets[facet['id']] = _f['facet'][dim_key]
             json_facets[facet['id']] = _f['facet'][dim_key]
         elif facet['type'] == 'function':
         elif facet['type'] == 'function':
           if facet['properties']['facets']:
           if facet['properties']['facets']:
+            json_facets[facet['id']] = self._get_aggregate_function(facet['properties']['facets'][0])
             if facet['properties']['compare']['is_enabled']:
             if facet['properties']['compare']['is_enabled']:
               # TODO: global compare override
               # TODO: global compare override
+              unit = re.split('\d+', facet['properties']['compare']['gap'])[1]
               json_facets[facet['id']] = {
               json_facets[facet['id']] = {
-                'type': "range",
+                'type': 'range',
                 'field': collection['timeFilter'].get('field'),
                 'field': collection['timeFilter'].get('field'),
-                'start': "2014-05-04T01:35:00Z/HOURS",
-                'end': "2014-05-04T14:15:00Z/HOURS",
-                'gap': "+12HOURS",
-                'facet': {facet['id']: self._get_aggregate_function(facet['properties']['facets'][0])}
+                'start': 'NOW/%s-%s-%s' % (unit, facet['properties']['compare']['gap'], facet['properties']['compare']['gap']),
+                'end': 'NOW/%s' % unit,
+                'gap': '+%(gap)s' % facet['properties']['compare'],
+                'facet': {facet['id']: json_facets[facet['id']]}
               }
               }
-            elif True:
+            if facet['properties']['filter']['is_enabled']:
               json_facets[facet['id']] = {
               json_facets[facet['id']] = {
-                'type': "query",
-                'q': 'bytes:[1000 TO *]',
-                'facet': {facet['id']: self._get_aggregate_function(facet['properties']['facets'][0])}
+                'type': 'query',
+                'q': facet['properties']['filter']['query'] or EMPTY_QUERY.get(),
+                'facet': {facet['id']: json_facets[facet['id']]}
               }
               }
-            else:
-              json_facets[facet['id']] = self._get_aggregate_function(facet['properties']['facets'][0])
             json_facets['processEmpty'] = True
             json_facets['processEmpty'] = True
         elif facet['type'] == 'pivot':
         elif facet['type'] == 'pivot':
           if facet['properties']['facets'] or facet['widgetType'] == 'map-widget':
           if facet['properties']['facets'] or facet['widgetType'] == 'map-widget':