소스 검색

[search] Plugged in all the variables for the charts and grid displaying

Enrico Berti 10 년 전
부모
커밋
f22bda7
3개의 변경된 파일241개의 추가작업 그리고 40개의 파일을 삭제
  1. 90 0
      apps/search/src/search/models.py
  2. 42 20
      apps/search/src/search/static/search/js/search.ko.js
  3. 109 20
      apps/search/src/search/templates/search.mako

+ 90 - 0
apps/search/src/search/models.py

@@ -287,6 +287,28 @@ class Collection(models.Model):
       props['collection']['template']['showGrid'] = True
     if 'showChart' not in props['collection']['template']:
       props['collection']['template']['showChart'] = False
+    if 'chartSettings' not in props['collection']['template']:
+      props['collection']['template']['chartSettings'] = {}
+    if 'chartType' not in props['collection']['template']['chartSettings']:
+      props['collection']['template']['chartSettings']['chartType'] = 'barchart'
+    if 'chartSorting' not in props['collection']['template']['chartSettings']:
+      props['collection']['template']['chartSettings']['chartSorting'] = 'none'
+    if 'chartScatterGroup' not in props['collection']['template']['chartSettings']:
+      props['collection']['template']['chartSettings']['chartScatterGroup'] = None
+    if 'chartScatterSize' not in props['collection']['template']['chartSettings']:
+      props['collection']['template']['chartSettings']['chartScatterSize'] = None
+    if 'chartScope' not in props['collection']['template']['chartSettings']:
+      props['collection']['template']['chartSettings']['chartScope'] = 'world'
+    if 'chartX' not in props['collection']['template']['chartSettings']:
+      props['collection']['template']['chartSettings']['chartX'] = None
+    if 'chartYSingle' not in props['collection']['template']['chartSettings']:
+      props['collection']['template']['chartSettings']['chartYSingle'] = None
+    if 'chartYMulti' not in props['collection']['template']['chartSettings']:
+      props['collection']['template']['chartSettings']['chartYMulti'] = []
+    if 'chartData' not in props['collection']['template']['chartSettings']:
+      props['collection']['template']['chartSettings']['chartData'] = []
+    if 'chartMapLabel' not in props['collection']['template']['chartSettings']:
+      props['collection']['template']['chartSettings']['chartMapLabel'] = None
     for facet in props['collection']['facets']:
       properties = facet['properties']
       if 'gap' in properties and not 'initial_gap' in properties:
@@ -336,6 +358,18 @@ class Collection(models.Model):
       "showFieldList": True,
       "showGrid": True,
       "showChart": False,
+      "chartSettings": {
+        'chartType': 'barchart',
+        'chartSorting': 'none',
+        'chartScatterGroup': None,
+        'chartScatterSize': None,
+        'chartScope': 'world',
+        'chartX': None,
+        'chartYSingle': None,
+        'chartYMulti': [],
+        'chartData': [],
+        'chartMapLabel': None,
+      },
       "fieldsAttributes": [self._make_gridlayout_header_field(field) for field in fields],
       "fieldsSelected": [],
       "leafletmap": {'latitudeField': None, 'longitudeField': None, 'labelField': None},
@@ -392,6 +426,28 @@ class Collection(models.Model):
         properties_python['collection']['template']['showGrid'] = True
       if 'showChart' not in properties_python['collection']['template']:
         properties_python['collection']['template']['showChart'] = False
+      if 'chartSettings' not in properties_python['collection']['template']:
+        properties_python['collection']['template']['chartSettings'] = {}
+      if 'chartType' not in properties_python['collection']['template']['chartSettings']:
+        properties_python['collection']['template']['chartSettings']['chartType'] = 'barchart'
+      if 'chartSorting' not in properties_python['collection']['template']['chartSettings']:
+        properties_python['collection']['template']['chartSettings']['chartSorting'] = 'none'
+      if 'chartScatterGroup' not in properties_python['collection']['template']['chartSettings']:
+        properties_python['collection']['template']['chartSettings']['chartScatterGroup'] = None
+      if 'chartScatterSize' not in properties_python['collection']['template']['chartSettings']:
+        properties_python['collection']['template']['chartSettings']['chartScatterSize'] = None
+      if 'chartScope' not in properties_python['collection']['template']['chartSettings']:
+        properties_python['collection']['template']['chartSettings']['chartScope'] = 'world'
+      if 'chartX' not in properties_python['collection']['template']['chartSettings']:
+        properties_python['collection']['template']['chartSettings']['chartX'] = None
+      if 'chartYSingle' not in properties_python['collection']['template']['chartSettings']:
+        properties_python['collection']['template']['chartSettings']['chartYSingle'] = None
+      if 'chartYMulti' not in properties_python['collection']['template']['chartSettings']:
+        properties_python['collection']['template']['chartSettings']['chartYMulti'] = []
+      if 'chartData' not in properties_python['collection']['template']['chartSettings']:
+        properties_python['collection']['template']['chartSettings']['chartData'] = []
+      if 'chartMapLabel' not in properties_python['collection']['template']['chartSettings']:
+        properties_python['collection']['template']['chartSettings']['chartMapLabel'] = None
 
     return properties_python
 
@@ -483,6 +539,28 @@ class Collection2(object):
       props['collection']['template']['showGrid'] = True
     if 'showChart' not in props['collection']['template']:
       props['collection']['template']['showChart'] = False
+    if 'chartSettings' not in props['collection']['template']:
+      props['collection']['template']['chartSettings'] = {}
+    if 'chartType' not in props['collection']['template']['chartSettings']:
+      props['collection']['template']['chartSettings']['chartType'] = 'barchart'
+    if 'chartSorting' not in props['collection']['template']['chartSettings']:
+      props['collection']['template']['chartSettings']['chartSorting'] = 'none'
+    if 'chartScatterGroup' not in props['collection']['template']['chartSettings']:
+      props['collection']['template']['chartSettings']['chartScatterGroup'] = None
+    if 'chartScatterSize' not in props['collection']['template']['chartSettings']:
+      props['collection']['template']['chartSettings']['chartScatterSize'] = None
+    if 'chartScope' not in props['collection']['template']['chartSettings']:
+      props['collection']['template']['chartSettings']['chartScope'] = 'world'
+    if 'chartX' not in props['collection']['template']['chartSettings']:
+      props['collection']['template']['chartSettings']['chartX'] = None
+    if 'chartYSingle' not in props['collection']['template']['chartSettings']:
+      props['collection']['template']['chartSettings']['chartYSingle'] = None
+    if 'chartYMulti' not in props['collection']['template']['chartSettings']:
+      props['collection']['template']['chartSettings']['chartYMulti'] = []
+    if 'chartData' not in props['collection']['template']['chartSettings']:
+      props['collection']['template']['chartSettings']['chartData'] = []
+    if 'chartMapLabel' not in props['collection']['template']['chartSettings']:
+      props['collection']['template']['chartSettings']['chartMapLabel'] = None
     if 'enabled' not in props['collection']:
       props['collection']['enabled'] = True
     if 'leafletmap' not in props['collection']['template']:
@@ -548,6 +626,18 @@ class Collection2(object):
       "showFieldList": True,
       "showGrid": True,
       "showChart": False,
+      "chartSettings" : {
+        'chartType': 'barchart',
+        'chartSorting': 'none',
+        'chartScatterGroup': None,
+        'chartScatterSize': None,
+        'chartScope': 'world',
+        'chartX': None,
+        'chartYSingle': None,
+        'chartYMulti': [],
+        'chartData': [],
+        'chartMapLabel': None,
+      },
       "fieldsAttributes": [self._make_gridlayout_header_field(field) for field in fields],
       "fieldsSelected": [],
       "leafletmap": {'latitudeField': None, 'longitudeField': None, 'labelField': None},

+ 42 - 20
apps/search/src/search/static/search/js/search.ko.js

@@ -833,6 +833,48 @@ var Collection = function (vm, collection) {
     });
   });
 
+  self.template.getMeta = function (extraCheck) {
+    return $.map(self.template.fieldsAttributes(), function (field) {
+      if (field.name() != '' && extraCheck(field.type())) {
+        return field;
+      }
+    }).sort(function (a, b) {
+      return a.name().toLowerCase().localeCompare(b.name().toLowerCase());
+    });
+  }
+
+  function alwaysTrue() {
+    return true;
+  }
+
+  function isNumericColumn(type) {
+    return $.inArray(type, ['tfloat', 'tint', 'tlong', 'tdouble', 'plong', 'pint', 'pfloat', 'pdouble', 'currency', 'long', 'int', 'float', 'double']) > -1;
+  }
+
+  function isDateTimeColumn(type) {
+    return $.inArray(type, ['tdate', 'pdate', 'date']) > -1;
+  }
+
+  function isStringColumn(type) {
+    return !isNumericColumn(type) && !isDateTimeColumn(type);
+  }
+
+  self.template.cleanedMeta = ko.computed(function () {
+    return self.template.getMeta(alwaysTrue);
+  });
+
+  self.template.cleanedNumericMeta = ko.computed(function () {
+    return self.template.getMeta(isNumericColumn);
+  });
+
+  self.template.cleanedStringMeta = ko.computed(function () {
+    return self.template.getMeta(isStringColumn);
+  });
+
+  self.template.cleanedDateTimeMeta = ko.computed(function () {
+    return self.template.getMeta(isDateTimeColumn);
+  });
+
   self.getTemplateField = function (name) {
     var _field = null;
     $.each(self.template.fields(), function (index, field) {
@@ -1246,26 +1288,6 @@ var SearchViewModel = function (collection_json, query_json, initial_json) {
 
   self.isPlayerMode = ko.observable(false);
 
-  var snippet = {};
-
-  self.chartType = ko.observable(typeof snippet.chartType != "undefined" && snippet.chartType != null ? snippet.chartType : ko.HUE_CHARTS.TYPES.BARCHART);
-  self.chartSorting = ko.observable(typeof snippet.chartSorting != "undefined" && snippet.chartSorting != null ? snippet.chartSorting : "none");
-  self.chartScatterGroup = ko.observable(typeof snippet.chartScatterGroup != "undefined" && snippet.chartScatterGroup != null ? snippet.chartScatterGroup : null);
-  self.chartScatterSize = ko.observable(typeof snippet.chartScatterSize != "undefined" && snippet.chartScatterSize != null ? snippet.chartScatterSize : null);
-  self.chartScope = ko.observable(typeof snippet.chartScope != "undefined" && snippet.chartScope != null ? snippet.chartScope : "world");
-  self.chartX = ko.observable(typeof snippet.chartX != "undefined" && snippet.chartX != null ? snippet.chartX : null);
-  self.chartYSingle = ko.observable(typeof snippet.chartYSingle != "undefined" && snippet.chartYSingle != null ? snippet.chartYSingle : null);
-  self.chartYMulti = ko.observableArray(typeof snippet.chartYMulti != "undefined" && snippet.chartYMulti != null ? snippet.chartYMulti : []);
-  self.chartData = ko.observableArray(typeof snippet.chartData != "undefined" && snippet.chartData != null ? snippet.chartData : []);
-  self.chartMapLabel = ko.observable(typeof snippet.chartMapLabel != "undefined" && snippet.chartMapLabel != null ? snippet.chartMapLabel : null);
-
-  self.hasDataForChart = ko.computed(function () {
-    if (self.chartType() == ko.HUE_CHARTS.TYPES.BARCHART || self.chartType() == ko.HUE_CHARTS.TYPES.LINECHART) {
-      return typeof self.chartX() != "undefined" && self.chartX() != null && self.chartYMulti().length > 0;
-    }
-    return typeof self.chartX() != "undefined" && self.chartX() != null && typeof self.chartYSingle() != "undefined" && self.chartYSingle() != null ;
-  });
-
   function bareWidgetBuilder(name, type){
     return new Widget({
       size: 12,

+ 109 - 20
apps/search/src/search/templates/search.mako

@@ -546,27 +546,28 @@ ${ dashboard.layout_skeleton() }
   <div class="grid-row">
 
     <div class="grid-left-bar">
-      <div style="opacity:1">
+      <div>
+        <!-- ko if: $root.response && $root.response().response && $root.response().response.numFound > 0 -->
         <div style="margin-top:3px">
           <a class="grid-side-btn active" href="javascript: void(0)"
              data-bind="click: function() { $root.collection.template.showChart(false); $root.collection.template.showGrid(true); }, css: {'active': $root.collection.template.showGrid() }" title="${_('Grid')}">
-            <i class="fa fa-fw fa-th"></i>
+            <i class="fa fa-th"></i>
           </a>
         </div>
 
         <div class="dropdown">
           <a class="grid-side-btn" style="padding-right:0" href="javascript: void(0)"
              data-bind="css: {'active': $root.collection.template.showChart() }, click: function() { $root.collection.template.showChart(true); $root.collection.template.showGrid(false); }">
-            <i class="hcha hcha-bar-chart" data-bind="visible: $root.chartType() == ko.HUE_CHARTS.TYPES.BARCHART"></i>
-            <i class="hcha hcha-line-chart" data-bind="visible: $root.chartType() == ko.HUE_CHARTS.TYPES.LINECHART"
+            <i class="hcha hcha-bar-chart" data-bind="visible: $root.collection.template.chartSettings.chartType() == ko.HUE_CHARTS.TYPES.BARCHART"></i>
+            <i class="hcha hcha-line-chart" data-bind="visible: $root.collection.template.chartSettings.chartType() == ko.HUE_CHARTS.TYPES.LINECHART"
                style="display: none;"></i>
-            <i class="hcha hcha-pie-chart" data-bind="visible: $root.chartType() == ko.HUE_CHARTS.TYPES.PIECHART"
+            <i class="hcha hcha-pie-chart" data-bind="visible: $root.collection.template.chartSettings.chartType() == ko.HUE_CHARTS.TYPES.PIECHART"
                style="display: none;"></i>
             <i class="fa fa-fw fa-dot-circle-o"
-               data-bind="visible: $root.chartType() == ko.HUE_CHARTS.TYPES.SCATTERCHART" style="display: none;"></i>
-            <i class="fa fa-fw fa-map-marker" data-bind="visible: $root.chartType() == ko.HUE_CHARTS.TYPES.MAP"
+               data-bind="visible: $root.collection.template.chartSettings.chartType() == ko.HUE_CHARTS.TYPES.SCATTERCHART" style="display: none;"></i>
+            <i class="fa fa-fw fa-map-marker" data-bind="visible: $root.collection.template.chartSettings.chartType() == ko.HUE_CHARTS.TYPES.MAP"
                style="display: none;"></i>
-            <i class="hcha hcha-map-chart" data-bind="visible: $root.chartType() == ko.HUE_CHARTS.TYPES.GRADIENTMAP"
+            <i class="hcha hcha-map-chart" data-bind="visible: $root.collection.template.chartSettings.chartType() == ko.HUE_CHARTS.TYPES.GRADIENTMAP"
                style="display: none;"></i>
           </a>
           <a class="dropdown-toggle grid-side-btn" style="padding:0" data-toggle="dropdown"
@@ -577,38 +578,38 @@ ${ dashboard.layout_skeleton() }
           <ul class="dropdown-menu">
             <li>
               <a href="javascript:void(0)"
-                 data-bind="css: {'active': $root.chartType() == ko.HUE_CHARTS.TYPES.BARCHART}, click: function(){ $root.chartType(ko.HUE_CHARTS.TYPES.BARCHART); }"
+                 data-bind="css: {'active': $root.collection.template.chartSettings.chartType() == ko.HUE_CHARTS.TYPES.BARCHART}, click: function(){ $root.collection.template.chartSettings.chartType(ko.HUE_CHARTS.TYPES.BARCHART); }"
                  class="active">
                 <i class="hcha hcha-bar-chart"></i> Bars
               </a>
             </li>
             <li>
               <a href="javascript:void(0)"
-                 data-bind="css: {'active': $root.chartType() == ko.HUE_CHARTS.TYPES.LINECHART}, click: function(){ $root.chartType(ko.HUE_CHARTS.TYPES.LINECHART); }">
+                 data-bind="css: {'active': $root.collection.template.chartSettings.chartType() == ko.HUE_CHARTS.TYPES.LINECHART}, click: function(){ $root.collection.template.chartSettings.chartType(ko.HUE_CHARTS.TYPES.LINECHART); }">
                 <i class="hcha hcha-line-chart"></i> Lines
               </a>
             </li>
             <li>
               <a href="javascript:void(0)"
-                 data-bind="css: {'active': $root.chartType() == ko.HUE_CHARTS.TYPES.PIECHART}, click: function(){ $root.chartType(ko.HUE_CHARTS.TYPES.PIECHART); }">
+                 data-bind="css: {'active': $root.collection.template.chartSettings.chartType() == ko.HUE_CHARTS.TYPES.PIECHART}, click: function(){ $root.collection.template.chartSettings.chartType(ko.HUE_CHARTS.TYPES.PIECHART); }">
                 <i class="hcha hcha-pie-chart"></i> Pie
               </a>
             </li>
             <li>
               <a href="javascript:void(0)"
-                 data-bind="css: {'active': $root.chartType() == ko.HUE_CHARTS.TYPES.SCATTERCHART}, click: function(){ $root.chartType(ko.HUE_CHARTS.TYPES.SCATTERCHART); }">
+                 data-bind="css: {'active': $root.collection.template.chartSettings.chartType() == ko.HUE_CHARTS.TYPES.SCATTERCHART}, click: function(){ $root.collection.template.chartSettings.chartType(ko.HUE_CHARTS.TYPES.SCATTERCHART); }">
                 <i class="fa fa-fw fa-dot-circle-o chart-icon"></i> Scatter
               </a>
             </li>
             <li>
               <a href="javascript:void(0)"
-                 data-bind="css: {'active': $root.chartType() == ko.HUE_CHARTS.TYPES.MAP}, click: function(){ $root.chartType(ko.HUE_CHARTS.TYPES.MAP); }">
+                 data-bind="css: {'active': $root.collection.template.chartSettings.chartType() == ko.HUE_CHARTS.TYPES.MAP}, click: function(){ $root.collection.template.chartSettings.chartType(ko.HUE_CHARTS.TYPES.MAP); }">
                 <i class="fa fa-fw fa-map-marker chart-icon"></i> Marker Map
               </a>
             </li>
             <li>
               <a href="javascript:void(0)"
-                 data-bind="css: {'active': $root.chartType() == ko.HUE_CHARTS.TYPES.GRADIENTMAP}, click: function(){ $root.chartType(ko.HUE_CHARTS.TYPES.GRADIENTMAP); }">
+                 data-bind="css: {'active': $root.collection.template.chartSettings.chartType() == ko.HUE_CHARTS.TYPES.GRADIENTMAP}, click: function(){ $root.collection.template.chartSettings.chartType(ko.HUE_CHARTS.TYPES.GRADIENTMAP); }">
                 <i class="hcha hcha-map-chart"></i> Gradient Map
               </a>
             </li>
@@ -617,9 +618,8 @@ ${ dashboard.layout_skeleton() }
 
         <div>
           <a class="grid-side-btn" href="javascript:void(0)" data-bind="click: function(){ $root.collection.template.showFieldList(!$root.collection.template.showFieldList()) }, css: { 'blue' : $root.collection.template.showFieldList() }"><i
-              class="fa fa-fw fa-cog"></i></a>
+              class="fa fa-cog"></i></a>
         </div>
-        <!-- ko if: $root.response && $root.response().response && $root.response().response.numFound > 0 -->
         <form method="POST" action="${ url('search:download') }" style="display:inline">
           ${ csrf_token(request) | n,unicode }
           <input type="hidden" name="collection" data-bind="value: ko.mapping.toJSON($root.collection)"/>
@@ -628,7 +628,7 @@ ${ dashboard.layout_skeleton() }
           <input type="hidden" name="type" value="">
           <div class="dropdown">
             <a class="grid-side-btn dropdown-toggle" style="padding-left:7px" data-toggle="dropdown">
-              <i class="fa fa-fw fa-download"></i>
+              <i class="fa fa-download"></i>
             </a>
             <ul class="dropdown-menu">
               <li>
@@ -686,17 +686,17 @@ ${ dashboard.layout_skeleton() }
     </div>
 
     <div>
-      <div class="widget-spinner" data-bind="visible: ! $root.hasRetrievedResults()">
+      <div class="widget-spinner" data-bind="visible: ! $root.hasRetrievedResults() || !$root.response().response">
         <!--[if !IE]> --><i class="fa fa-spinner fa-spin"></i><!-- <![endif]-->
         <!--[if IE]><img src="${ static('desktop/art/spinner.gif') }" /><![endif]-->
       </div>
 
-      <div data-bind="visible: $root.hasRetrievedResults() && $root.results().length == 0">
+      <div data-bind="visible: $root.hasRetrievedResults() && $root.results().length == 0 && $root.response().response">
         <br/>
         ${ _('Your search did not match any documents.') }
       </div>
 
-      <div data-bind="visible: $root.hasRetrievedResults() && $root.results().length > 0">
+      <div data-bind="visible: $root.hasRetrievedResults() && $root.results().length > 0 && $root.collection.template.showGrid()">
         <!-- ko if: $root.response().response -->
           <div data-bind="template: {name: 'resultset-pagination', data: $root.response()}" style="padding: 8px; color: #666"></div>
         <!-- /ko -->
@@ -732,12 +732,99 @@ ${ dashboard.layout_skeleton() }
           </table>
         </div>
       </div>
+
+      <div data-bind="visible: $root.hasRetrievedResults() && $root.results().length > 0 && $root.collection.template.showChart()">
+        <span data-bind="template: {name: 'grid-chart-settings', data: $root.collection.template.chartSettings}"></span>
+      </div>
+
       </div>
     </div>
     </div>
   <!-- /ko -->
 </script>
 
+<script type="text/html" id="grid-chart-settings">
+  <div>
+    <ul class="nav nav-list" style="border: none; background-color: #FFF" data-bind="visible: chartType() != ''">
+      <li data-bind="visible: [ko.HUE_CHARTS.TYPES.MAP, ko.HUE_CHARTS.TYPES.GRADIENTMAP, ko.HUE_CHARTS.TYPES.PIECHART].indexOf(chartType()) == -1" class="nav-header">${_('x-axis')}</li>
+      <li data-bind="visible: chartType() == ko.HUE_CHARTS.TYPES.GRADIENTMAP" class="nav-header">${_('region')}</li>
+      <li data-bind="visible: chartType() == ko.HUE_CHARTS.TYPES.MAP" class="nav-header">${_('latitude')}</li>
+      <li data-bind="visible: chartType() == ko.HUE_CHARTS.TYPES.PIECHART" class="nav-header">${_('legend')}</li>
+    </ul>
+    <div data-bind="visible: chartType() != ''">
+      <select data-bind="options: (chartType() == ko.HUE_CHARTS.TYPES.BARCHART || chartType() == ko.HUE_CHARTS.TYPES.PIECHART || chartType() == ko.HUE_CHARTS.TYPES.GRADIENTMAP) ? $root.collection.template.cleanedMeta : $root.collection.template.cleanedNumericMeta, value: chartX, optionsText: 'name', optionsValue: 'name', optionsCaption: '${_ko('Choose a column...')}', select2: { width: '100%', placeholder: '${ _ko("Choose a column...") }', update: chartX}" class="input-medium"></select>
+    </div>
+
+    <ul class="nav nav-list" style="border: none; background-color: #FFF" data-bind="visible: chartType() != ''">
+      <li data-bind="visible: [ko.HUE_CHARTS.TYPES.MAP, ko.HUE_CHARTS.TYPES.GRADIENTMAP, ko.HUE_CHARTS.TYPES.PIECHART].indexOf(chartType()) == -1" class="nav-header">${_('y-axis')}</li>
+      <li data-bind="visible: chartType() == ko.HUE_CHARTS.TYPES.GRADIENTMAP" class="nav-header">${_('value')}</li>
+      <li data-bind="visible: chartType() == ko.HUE_CHARTS.TYPES.MAP" class="nav-header">${_('longitude')}</li>
+      <li data-bind="visible: chartType() == ko.HUE_CHARTS.TYPES.PIECHART" class="nav-header">${_('value')}</li>
+    </ul>
+
+    <div style="overflow-y: scroll; max-height: 220px" data-bind="visible: chartType() != '' && (chartType() == ko.HUE_CHARTS.TYPES.BARCHART || chartType() == ko.HUE_CHARTS.TYPES.LINECHART)">
+      <ul class="unstyled" data-bind="foreach: $root.collection.template.cleanedNumericMeta">
+        <li><input type="checkbox" data-bind="checkedValue: name, checked: $parent.chartYMulti" /> <span data-bind="text: $data.name"></span></li>
+      </ul>
+    </div>
+    <div data-bind="visible: chartType() == ko.HUE_CHARTS.TYPES.PIECHART || chartType() == ko.HUE_CHARTS.TYPES.MAP || chartType() == ko.HUE_CHARTS.TYPES.GRADIENTMAP || chartType() == ko.HUE_CHARTS.TYPES.SCATTERCHART">
+      <select data-bind="options: chartType() == ko.HUE_CHARTS.TYPES.GRADIENTMAP ? $root.collection.template.cleanedMeta : $root.collection.template.cleanedNumericMeta, value: chartYSingle, optionsText: 'name', optionsValue: 'name', optionsCaption: '${_ko('Choose a column...')}', select2: { width: '100%', placeholder: '${ _ko("Choose a column...") }', update: chartYSingle}" class="input-medium"></select>
+    </div>
+
+    <ul class="nav nav-list" style="border: none; background-color: #FFF" data-bind="visible: chartType() != '' && chartType() == ko.HUE_CHARTS.TYPES.MAP">
+      <li class="nav-header">${_('label')}</li>
+    </ul>
+    <div data-bind="visible: chartType() == ko.HUE_CHARTS.TYPES.MAP">
+      <select data-bind="options: $root.collection.template.cleanedMeta, value: chartMapLabel, optionsText: 'name', optionsValue: 'name', optionsCaption: '${_ko('Choose a column...')}', select2: { width: '100%', placeholder: '${ _ko("Choose a column...") }', update: chartMapLabel}" class="input-medium"></select>
+    </div>
+
+    <ul class="nav nav-list" style="border: none; background-color: #FFF" data-bind="visible: chartType() != '' && chartType() == ko.HUE_CHARTS.TYPES.SCATTERCHART">
+      <li class="nav-header">${_('scatter group')}</li>
+    </ul>
+    <div data-bind="visible: chartType() != '' && chartType() == ko.HUE_CHARTS.TYPES.SCATTERCHART">
+      <select data-bind="options: $root.collection.template.cleanedMeta, value: chartScatterGroup, optionsText: 'name', optionsValue: 'name', optionsCaption: '${_ko('Choose a column...')}', select2: { width: '100%', placeholder: '${ _ko("Choose a column...") }', update: chartScatterGroup}" class="input-medium"></select>
+    </div>
+
+    <ul class="nav nav-list" style="border: none; background-color: #FFF" data-bind="visible: chartType() == ko.HUE_CHARTS.TYPES.SCATTERCHART">
+      <li class="nav-header">${_('scatter size')}</li>
+    </ul>
+    <div data-bind="visible: chartType() == ko.HUE_CHARTS.TYPES.SCATTERCHART">
+      <select data-bind="options: $root.collection.template.cleanedMeta, value: chartScatterSize, optionsText: 'name', optionsValue: 'name', optionsCaption: '${_ko('Choose a column...')}', select2: { width: '100%', placeholder: '${ _ko("Choose a column...") }', update: chartScatterSize}" class="input-medium"></select>
+    </div>
+
+    <!-- ko if: chartType() != '' && chartType() == ko.HUE_CHARTS.TYPES.GRADIENTMAP -->
+    <ul class="nav nav-list" style="border: none; background-color: #FFF">
+      <li class="nav-header">${_('scope')}</li>
+    </ul>
+    <div data-bind="visible: chartType() != ''">
+      <select data-bind="selectedOptions: chartScope, optionsCaption: '${_ko('Choose a scope...')}', select2: { width: '100%', placeholder: '${ _ko("Choose a scope...") }', update: chartScope}">
+        <option value="world">${ _("World") }</option>
+        <option value="europe">${ _("Europe") }</option>
+        <option value="aus">${ _("Australia") }</option>
+        <option value="bra">${ _("Brazil") }</option>
+        <option value="can">${ _("Canada") }</option>
+        <option value="chn">${ _("China") }</option>
+        <option value="fra">${ _("France") }</option>
+        <option value="deu">${ _("Germany") }</option>
+        <option value="ita">${ _("Italy") }</option>
+        <option value="jpn">${ _("Japan") }</option>
+        <option value="gbr">${ _("UK") }</option>
+        <option value="usa">${ _("USA") }</option>
+      </select>
+    </div>
+    <!-- /ko -->
+
+    <ul class="nav nav-list" style="border: none; background-color: #FFF" data-bind="visible: chartType() != '' && chartType() != ko.HUE_CHARTS.TYPES.MAP && chartType() != ko.HUE_CHARTS.TYPES.GRADIENTMAP && chartType() != ko.HUE_CHARTS.TYPES.SCATTERCHART">
+      <li class="nav-header">${_('sorting')}</li>
+    </ul>
+    <div class="btn-group" data-toggle="buttons-radio" data-bind="visible: chartType() != '' && chartType() != ko.HUE_CHARTS.TYPES.MAP && chartType() != ko.HUE_CHARTS.TYPES.GRADIENTMAP && chartType() != ko.HUE_CHARTS.TYPES.SCATTERCHART">
+      <a rel="tooltip" data-placement="top" title="${_('No sorting')}" href="javascript:void(0)" class="btn" data-bind="css: {'active': chartSorting() == 'none'}, click: function(){ chartSorting('none'); }"><i class="fa fa-align-left fa-rotate-270"></i></a>
+      <a rel="tooltip" data-placement="top" title="${_('Sort ascending')}" href="javascript:void(0)" class="btn" data-bind="css: {'active': chartSorting() == 'asc'}, click: function(){ chartSorting('asc'); }"><i class="fa fa-sort-amount-asc fa-rotate-270"></i></a>
+      <a rel="tooltip" data-placement="top" title="${_('Sort descending')}" href="javascript:void(0)" class="btn" data-bind="css: {'active': chartSorting() == 'desc'}, click: function(){ chartSorting('desc'); }"><i class="fa fa-sort-amount-desc fa-rotate-270"></i></a>
+    </div>
+  </div>
+</script>
+
 <script type="text/html" id="html-resultset-widget">
   <!-- ko ifnot: $root.collection.template.isGridLayout() -->
     <div data-bind="visible: $root.isEditing" style="margin-bottom: 20px">
@@ -2001,6 +2088,7 @@ ${ dashboard.layout_skeleton() }
 <link rel="stylesheet" href="${ static('desktop/ext/css/hue-filetypes.css') }">
 <link rel="stylesheet" href="${ static('desktop/ext/css/hue-charts.css') }">
 <link rel="stylesheet" href="${ static('desktop/ext/chosen/chosen.min.css') }">
+<link rel="stylesheet" href="${ static('desktop/ext/select2/select2.css') }">
 
 <script src="${ static('desktop/js/hue.json.js') }" type="text/javascript" charset="utf-8"></script>
 <script src="${ static('desktop/ext/js/moment-with-locales.min.js') }" type="text/javascript" charset="utf-8"></script>
@@ -2015,6 +2103,7 @@ ${ dashboard.import_layout(True) }
 <script src="${ static('desktop/ext/js/mustache.js') }" type="text/javascript" charset="utf-8"></script>
 <script src="${ static('desktop/ext/chosen/chosen.jquery.min.js') }" type="text/javascript" charset="utf-8"></script>
 <script src="${ static('desktop/ext/js/jquery/plugins/jquery.hotkeys.js') }"></script>
+<script src="${ static('desktop/ext/select2/select2.min.js') }" type="text/javascript" charset="utf-8"></script>
 
 <script src="${ static('search/js/search.ko.js') }" type="text/javascript" charset="utf-8"></script>