Răsfoiți Sursa

HUE-2173 [dashboard] Refactor model to support N dimensions: UI part

Romain Rigaux 8 ani în urmă
părinte
comite
8de4611

+ 8 - 4
desktop/libs/dashboard/src/dashboard/api.py

@@ -34,7 +34,8 @@ from dashboard.dashboard_api import get_engine
 from dashboard.data_export import download as export_download
 from dashboard.decorators import allow_viewer_only
 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
 
 
 LOG = logging.getLogger(__name__)
@@ -381,7 +382,7 @@ def _create_facet(collection, user, facet_id, facet_label, facet_field, widget_t
     facet_type = 'nested'
     properties['facets'] = []
     properties['domain'] = {'blockParent': [], 'blockChildren': []}
-    properties['facets_form'] = {'field': '', 'mincount': 1, 'limit': 5, 'sort': 'desc', 'aggregate': {'function': 'unique', 'formula': '', 'plain_formula': '', 'percentiles': [{'value': 50}]}}
+    properties['facets_form'] = NESTED_FACET_FORM
     properties['scope'] = 'world'
     properties['limit'] = 100
   else:
@@ -406,8 +407,11 @@ def _create_facet(collection, user, facet_id, facet_label, facet_field, widget_t
       else:
         facet_type = 'nested'
 
-      properties['facets_form'] = {'field': '', 'mincount': 1, 'limit': 5, 'sort': 'desc', 'aggregate': {'function': 'unique', 'formula': '', 'plain_formula': '', 'percentiles': [{'value': 50}]}}
-      properties['facets'] = []
+      properties['facets_form'] = NESTED_FACET_FORM
+      facet = NESTED_FACET_FORM.copy()
+      facet['field'] = facet_field
+      facet['aggregate']['function'] = 'count'
+      properties['facets'] = [facet]
       properties['domain'] = {'blockParent': [], 'blockChildren': []}
 
       if widget_type == 'pie2-widget':

+ 9 - 4
desktop/libs/dashboard/src/dashboard/static/dashboard/js/search.ko.js

@@ -698,8 +698,9 @@ var Collection = function (vm, collection) {
     }
   }
 
-  self._addObservablesToFacet = function(facet, vm) { console.log(facet.properties.facets_form.aggregate);
-    if (facet.properties.facets_form && facet.properties.facets_form.aggregate) { // Only Solr 5+
+  self._addObservablesToFacet = function(facet, vm) {
+    if (facet.properties) { // Very top facet
+	if (facet.properties.facets_form && facet.properties.facets_form.aggregate) { // Only Solr 5+
       facet.properties.facets_form.aggregate.metrics = ko.computed(function() {
         var _field = self.getTemplateField(facet.widgetType() == 'hit-widget' ? facet.field() : facet.properties.facets_form.field(), self.template.fieldsAttributes());
         return self._get_field_operations(_field, facet);
@@ -727,8 +728,9 @@ var Collection = function (vm, collection) {
         vm.search();
       });
     }
+    }
 
-    // For Hue 4 facets only
+    // For Solr 5+ facets only
     if (typeof facet.template != 'undefined') {
       facet.template.filteredAttributeFields = ko.computed(function() { // Dup of template.filteredAttributeFields
         var _fields = [];
@@ -937,7 +939,10 @@ var Collection = function (vm, collection) {
         	// "read only"
         	// .isLoading(false)
           } else {
-            self._addObservablesToFacet(facet, vm);
+            self._addObservablesToFacet(facet, vm); // Top widget
+            if (facet.properties.facets) { // Sub facet
+        	  self._addObservablesToFacet(facet.properties.facets()[0], vm);
+        	}
           }
 
           self.facets.push(facet);

+ 81 - 81
desktop/libs/dashboard/src/dashboard/templates/common_search.mako

@@ -571,75 +571,75 @@ ${ dashboard.layout_skeleton(suffix='search') }
 <script type="text/html" id="facet-toggle2">
   <div class="pull-left margin-right-20">
     ## Dimension 1
-  <!-- ko if: $root.isEditing -->
-    <!-- ko if: properties.canRange() && typeof properties.type != "undefined" -->
-    <div class="facet-field-cnt">
-      <span class="facet-field-label facet-field-label-fixed-width">${ _('Type') }</span>
-      <a href="javascript: void(0)" title="${ _('Toggle how to group the values') }" data-bind="click: $root.collection.toggleRangeFacet2">
-        <i class="fa" data-bind="css: { 'fa-arrows-h': properties.type() == 'range', 'fa-circle': properties.type() == 'field', 'fa-level-up': properties.type() == 'range-up' }, attr: { title: properties.type() == 'field' ? 'Range' : properties.type() == 'range-up' ? 'Range and up' : 'Term' }"></i>
-        <span data-bind="visible: properties.type() == 'range'">${_('range')}</span>
-        <span data-bind="visible: properties.type() == 'range-up'">${_('range & up')}</span>
-        <span data-bind="visible: properties.type() == 'field'">${_('field')}</span>
-      </a>
-    </div>
-    <!-- /ko -->
-
-    <!-- ko if: widgetType() != 'hit-widget' -->
-    <div class="facet-field-cnt">
-      <span class="facet-field-label facet-field-label-fixed-width">${ _('Sorting') }</span>
-      <a href="javascript: void(0)" title="${ _('Toggle sort order') }" data-bind="click:  function() { $root.collection.toggleSortFacet2($data, $data); }">
-        <i class="fa" data-bind="css: { 'fa-caret-down': properties.sort() == 'desc', 'fa-caret-up': properties.sort() == 'asc', 'fa-sort': properties.sort() == 'default' }"></i>
-        <span data-bind="visible: properties.sort() == 'desc'">${_('descending')}</span>
-        <span data-bind="visible: properties.sort() == 'asc'">${_('ascending')}</span>
-        <span data-bind="visible: properties.sort() == 'default'">${_('default')}</span>
-      </a>
-    </div>
-    <!-- /ko -->
-
-
-    <!-- ko if: type() == 'range' || type() == 'range-up' || (type() == 'nested' && typeof properties.min != "undefined") -->
-      <!-- ko ifnot: properties.isDate() -->
-        <div class="slider-cnt" data-bind="slider: {start: properties.min, end: properties.max, gap: properties.initial_gap, min: properties.initial_start, max: properties.initial_end, properties: properties, labels: SLIDER_LABELS}"></div>
-      <!-- /ko -->
-      <!-- ko if: properties.isDate() && $root.collection.timeFilter && $root.collection.timeFilter.field && $root.collection.timeFilter.field() != field() -->
-        <div data-bind="daterangepicker: {start: properties.start, end: properties.end, gap: properties.initial_gap, relatedgap: properties.gap, min: properties.min, max: properties.max}"></div>
-      <!-- /ko -->
-    <!-- /ko -->
-
-
-    <div class="facet-field-cnt">
-      <span class="spinedit-cnt">
-        <span class="facet-field-label facet-field-label-fixed-width">
-          ${ _('Limit') }
-        </span>
-        <input type="text" class="input-medium" data-bind="spinedit: properties.limit"/>
-      </span>
-    </div>
-
-    <div class="facet-field-cnt">
-      <span class="spinedit-cnt">
-        <span class="facet-field-label facet-field-label-fixed-width">
-          ${ _('Min Count') }
-        </span>
-        <input type="text" class="input-medium" data-bind="spinedit: properties.mincount"/>
-      </span>
-    </div>
-
-    <div class="facet-field-cnt" data-bind="visible: $root.collection.nested.enabled">
-      <span class="spinedit-cnt">
-        <span class="facet-field-label">
-          ${ _('Domain') }
-        </span>
-        ${ _('Parent') }
-        <select data-bind="selectedOptions: properties.domain.blockParent, options: $root.collection.nestedNames" size="5" multiple="true"></select>
-        ${ _('Children') }
-        <select data-bind="selectedOptions: properties.domain.blockChildren, options: $root.collection.nestedNames" size="5" multiple="true"></select>
-
-        <input type="text" class="input-medium" data-bind="spinedit: properties.mincount"/>
-      </span>
-    </div>
-  <!-- /ko -->
-  </div>
+##   <!-- ko if: $root.isEditing -->
+##     <!-- ko if: properties.canRange() && typeof properties.type != "undefined" -->
+##     <div class="facet-field-cnt">
+##       <span class="facet-field-label facet-field-label-fixed-width">${ _('Type') }</span>
+##       <a href="javascript: void(0)" title="${ _('Toggle how to group the values') }" data-bind="click: $root.collection.toggleRangeFacet2">
+##         <i class="fa" data-bind="css: { 'fa-arrows-h': properties.type() == 'range', 'fa-circle': properties.type() == 'field', 'fa-level-up': properties.type() == 'range-up' }, attr: { title: properties.type() == 'field' ? 'Range' : properties.type() == 'range-up' ? 'Range and up' : 'Term' }"></i>
+##         <span data-bind="visible: properties.type() == 'range'">${_('range')}</span>
+##         <span data-bind="visible: properties.type() == 'range-up'">${_('range & up')}</span>
+##         <span data-bind="visible: properties.type() == 'field'">${_('field')}</span>
+##       </a>
+##     </div>
+##     <!-- /ko -->
+## 
+##     <!-- ko if: widgetType() != 'hit-widget' -->
+##     <div class="facet-field-cnt">
+##       <span class="facet-field-label facet-field-label-fixed-width">${ _('Sorting') }</span>
+##       <a href="javascript: void(0)" title="${ _('Toggle sort order') }" data-bind="click:  function() { $root.collection.toggleSortFacet2($data, $data); }">
+##         <i class="fa" data-bind="css: { 'fa-caret-down': properties.sort() == 'desc', 'fa-caret-up': properties.sort() == 'asc', 'fa-sort': properties.sort() == 'default' }"></i>
+##         <span data-bind="visible: properties.sort() == 'desc'">${_('descending')}</span>
+##         <span data-bind="visible: properties.sort() == 'asc'">${_('ascending')}</span>
+##         <span data-bind="visible: properties.sort() == 'default'">${_('default')}</span>
+##       </a>
+##     </div>
+##     <!-- /ko -->
+## 
+## 
+##     <!-- ko if: type() == 'range' || type() == 'range-up' || (type() == 'nested' && typeof properties.min != "undefined") -->
+##       <!-- ko ifnot: properties.isDate() -->
+##         <div class="slider-cnt" data-bind="slider: {start: properties.min, end: properties.max, gap: properties.initial_gap, min: properties.initial_start, max: properties.initial_end, properties: properties, labels: SLIDER_LABELS}"></div>
+##       <!-- /ko -->
+##       <!-- ko if: properties.isDate() && $root.collection.timeFilter && $root.collection.timeFilter.field && $root.collection.timeFilter.field() != field() -->
+##         <div data-bind="daterangepicker: {start: properties.start, end: properties.end, gap: properties.initial_gap, relatedgap: properties.gap, min: properties.min, max: properties.max}"></div>
+##       <!-- /ko -->
+##     <!-- /ko -->
+## 
+## 
+##     <div class="facet-field-cnt">
+##       <span class="spinedit-cnt">
+##         <span class="facet-field-label facet-field-label-fixed-width">
+##           ${ _('Limit') }
+##         </span>
+##         <input type="text" class="input-medium" data-bind="spinedit: properties.limit"/>
+##       </span>
+##     </div>
+## 
+##     <div class="facet-field-cnt">
+##       <span class="spinedit-cnt">
+##         <span class="facet-field-label facet-field-label-fixed-width">
+##           ${ _('Min Count') }
+##         </span>
+##         <input type="text" class="input-medium" data-bind="spinedit: properties.mincount"/>
+##       </span>
+##     </div>
+## 
+##     <div class="facet-field-cnt" data-bind="visible: $root.collection.nested.enabled">
+##       <span class="spinedit-cnt">
+##         <span class="facet-field-label">
+##           ${ _('Domain') }
+##         </span>
+##         ${ _('Parent') }
+##         <select data-bind="selectedOptions: properties.domain.blockParent, options: $root.collection.nestedNames" size="5" multiple="true"></select>
+##         ${ _('Children') }
+##         <select data-bind="selectedOptions: properties.domain.blockChildren, options: $root.collection.nestedNames" size="5" multiple="true"></select>
+## 
+##         <input type="text" class="input-medium" data-bind="spinedit: properties.mincount"/>
+##       </span>
+##     </div>
+##   <!-- /ko -->
+##   </div>
 
   ## Dimensions > 1
   <!-- ko if: $root.isEditing -->
@@ -1770,19 +1770,19 @@ ${ dashboard.layout_skeleton(suffix='search') }
     <!-- ko with: $root.collection.getFacetById($parent.id()) -->
     <div>
 
-      <span data-bind="template: { name: 'metric-form' }"></span>
+      ##<span data-bind="template: { name: 'metric-form' }"></span>
       <span data-bind="template: { name: 'facet-toggle2' }"></span>
 
       <div class="pull-right" style="margin-top: 40px">
 
-        <div class="inline-block hide" style="padding-bottom: 10px; padding-right: 20px">
-          <span class="facet-field-label hide">${ _('Sorting') }</span>
-          <a href="javascript: void(0)" title="${ _('Toggle sort order') }" class="hide" data-bind="click: $root.collection.toggleSortFacet">
-            <i class="fa" data-bind="css: { 'fa-caret-down': properties.sort() == 'desc', 'fa-caret-up': properties.sort() == 'asc' }"></i>
-            <span data-bind="visible: properties.sort() == 'desc'">${_('descending')}</span>
-            <span data-bind="visible: properties.sort() == 'asc'">${_('ascending')}</span>
-          </a>
-        </div>
+        ##<div class="inline-block hide" style="padding-bottom: 10px; padding-right: 20px">
+        ##  <span class="facet-field-label hide">${ _('Sorting') }</span>
+        ##  <a href="javascript: void(0)" title="${ _('Toggle sort order') }" class="hide" data-bind="click: $root.collection.toggleSortFacet">
+        ##    <i class="fa" data-bind="css: { 'fa-caret-down': properties.sort() == 'desc', 'fa-caret-up': properties.sort() == 'asc' }"></i>
+        ##    <span data-bind="visible: properties.sort() == 'desc'">${_('descending')}</span>
+        ##    <span data-bind="visible: properties.sort() == 'asc'">${_('ascending')}</span>
+        ##  </a>
+        ##</div>
 
       <!-- ko if: properties.isDate -->
         <div class="inline-block" style="padding-bottom: 10px; padding-right: 20px">
@@ -2109,8 +2109,8 @@ ${ dashboard.layout_skeleton(suffix='search') }
         <select data-bind="options: $parent.properties.facets_form.aggregate.metrics, optionsText: 'label', optionsValue: 'value', value: $data.function" class="input-small"></select>
       <!-- /ko -->
 
-      <!-- ko if: ($data.function() != 'field' || typeof properties == "undefined") && $data.metrics -->
-        <select data-bind="options: $data.metrics, optionsText: 'label', optionsValue: 'value', value: $data.function" class="input-small"></select>
+      <!-- ko if: $data.function() != 'field' -->
+        <select data-bind="options: $parents[1].properties.facets_form.aggregate.metrics, optionsText: 'label', optionsValue: 'value', value: $data.function" class="input-small"></select>
       <!-- /ko -->
 
       <!-- ko if: $data.function() == 'percentile' -->
@@ -2133,7 +2133,7 @@ ${ dashboard.layout_skeleton(suffix='search') }
       <input data-bind="value: formula, visible: $parent.field() == 'formula', valueUpdate: 'afterkeydown'"></input>
       <input data-bind="value: plain_formula" type="hidden"></input>
 
-      <!-- ko if: $data.function() != 'field' && $data.metrics -->
+      <!-- ko if: $data.function() != 'field' -->
       <div class="facet-field-cnt">
         <span class="facet-field-label facet-field-label-fixed-width">${ _('Sorting') }</span>
         <a href="javascript: void(0)" title="${ _('Toggle sort order') }" data-bind="click: function() { $root.collection.toggleSortFacet2($parents[1], $parent); }">

+ 48 - 46
desktop/libs/libsolr/src/libsolr/api.py

@@ -143,58 +143,60 @@ class SolrApi(object):
               ('facet.field', '{!key=%(key)s ex=%(id)s f.%(field)s.facet.limit=%(limit)s f.%(field)s.facet.mincount=%(mincount)s}%(field)s' % keys),
           )
         elif facet['type'] == 'nested':
-          sort = {'count': facet['properties']['sort']}
-          for i, agg in enumerate(self._get_dimension_aggregates(facet['properties']['facets'])):
-            if agg['sort'] != 'default':
-              agg_function = self._get_aggregate_function(agg)
-              sort = {'agg_%02d_%02d:%s' % (1, i, agg_function): agg['sort']}
-
-          if sort.get('count') == 'default':
-            sort['count'] = 'desc'
-          _f = {
-              'field': facet['field'],
-              'limit': int(facet['properties'].get('limit', 10)) + (1 if facet['widgetType'] == 'text-facet-widget' else 0),
-              'mincount': int(facet['properties']['mincount']),
-              'sort': sort,
-          }
-
-          if facet['properties']['domain'].get('blockParent') or facet['properties']['domain'].get('blockChildren'):
-            _f['domain'] = {}
-            if facet['properties']['domain'].get('blockParent'):
-              _f['domain']['blockParent'] = ' OR '.join(facet['properties']['domain']['blockParent'])
-            if facet['properties']['domain'].get('blockChildren'):
-              _f['domain']['blockChildren'] = ' OR '.join(facet['properties']['domain']['blockChildren'])
-
-          if 'start' in facet['properties'] and not facet['properties'].get('type') == 'field':
-            _f.update({
-                'type': 'range',
-                'start': facet['properties']['start'],
-                'end': facet['properties']['end'],
-                'gap': facet['properties']['gap'],
-            })
-            if timeFilter and timeFilter['time_field'] == facet['field'] and (facet['id'] not in timeFilter['time_filter_overrides'] or facet['widgetType'] != 'bucket-widget'):
-              _f.update(self._get_time_filter_query(timeFilter, facet))
-          else:
-            _f.update({
-                'type': 'terms',
-                'field': facet['field'],
-                'excludeTags': facet['id'],
-                'offset': 0,
-                'numBuckets': True,
-                'allBuckets': True,
-                #'prefix': '' # Forbidden on numeric fields
-            })
-            if facet['properties']['canRange'] and not facet['properties']['isDate']:
-              del _f['mincount'] # Numeric fields do not support
-
+#           sort = {'count': facet['properties']['sort']}
+#           for i, agg in enumerate(self._get_dimension_aggregates(facet['properties']['facets'])):
+#             if agg['sort'] != 'default':
+#               agg_function = self._get_aggregate_function(agg)
+#               sort = {'agg_%02d_%02d:%s' % (1, i, agg_function): agg['sort']}
+# 
+#           if sort.get('count') == 'default':
+#             sort['count'] = 'desc'
+#           _f = {
+#               'field': facet['field'],
+#               'limit': int(facet['properties'].get('limit', 10)) + (1 if facet['widgetType'] == 'text-facet-widget' else 0),
+#               'mincount': int(facet['properties']['mincount']),
+#               'sort': sort,
+#           }
+# 
+#           if facet['properties']['domain'].get('blockParent') or facet['properties']['domain'].get('blockChildren'):
+#             _f['domain'] = {}
+#             if facet['properties']['domain'].get('blockParent'):
+#               _f['domain']['blockParent'] = ' OR '.join(facet['properties']['domain']['blockParent'])
+#             if facet['properties']['domain'].get('blockChildren'):
+#               _f['domain']['blockChildren'] = ' OR '.join(facet['properties']['domain']['blockChildren'])
+# 
+#           if 'start' in facet['properties'] and not facet['properties'].get('type') == 'field':
+#             _f.update({
+#                 'type': 'range',
+#                 'start': facet['properties']['start'],
+#                 'end': facet['properties']['end'],
+#                 'gap': facet['properties']['gap'],
+#             })
+#             if timeFilter and timeFilter['time_field'] == facet['field'] and (facet['id'] not in timeFilter['time_filter_overrides'] or facet['widgetType'] != 'bucket-widget'):
+#               _f.update(self._get_time_filter_query(timeFilter, facet))
+#           else:
+#             _f.update({
+#                 'type': 'terms',
+#                 'field': facet['field'],
+#                 'excludeTags': facet['id'],
+#                 'offset': 0,
+#                 'numBuckets': True,
+#                 'allBuckets': True,
+#                 #'prefix': '' # Forbidden on numeric fields
+#             })
+#             if facet['properties']['canRange'] and not facet['properties']['isDate']:
+#               del _f['mincount'] # Numeric fields do not support
+
+          _f = {}
           if facet['properties']['facets']:
             self._n_facet_dimension(facet, _f, facet['properties']['facets'], 1)
             if facet['widgetType'] == 'text-facet-widget':
               _fname = _f['facet'].keys()[0]
               _f['sort'] = {_fname: facet['properties']['sort']}
               # domain = '-d2:NaN' # Solr 6.4
-
-          json_facets[facet['id']] = _f
+          # _f = _f['facet']
+          print _f
+          json_facets[facet['id']] = _f['facet']['dim_01:country_code3']
         elif facet['type'] == 'function':
           json_facets[facet['id']] = self._get_aggregate_function(facet)
           json_facets['processEmpty'] = True