Browse Source

HUE-2676 [search] Support lines in the timeline

Added dropdown to select if it's either a bar chart or line chart
Enrico Berti 10 years ago
parent
commit
5411d54ddc

+ 6 - 0
apps/search/src/search/api.py

@@ -137,6 +137,12 @@ def _guess_range_facet(widget_type, solr_api, collection, facet_field, propertie
       'canRange': True,
       'isDate': is_date,
     })
+
+    if widget_type == 'histogram-widget':
+      properties.update({
+      'timelineChartType': 'bar'
+      })
+
   except Exception, e:
     print e
     # stats not supported on all the fields, like text

+ 17 - 0
apps/search/src/search/templates/search.mako

@@ -776,6 +776,11 @@ ${ dashboard.layout_skeleton() }
 
     <div style="padding-bottom: 10px; text-align: right; padding-right: 20px" data-bind="visible: counts.length > 0">
       <span data-bind="with: $root.collection.getFacetById($parent.id())">
+        <span class="facet-field-label">${ _('Chart Type') }</span>
+         <select class="input-small" data-bind="options: $root.timelineChartTypes,
+                       optionsText: 'label',
+                       optionsValue: 'value',
+                       value: properties.timelineChartType"></select>&nbsp;
         <span class="facet-field-label">${ _('Interval') }</span>
          <select class="input-small" data-bind="options: $root.intervalOptions,
                        optionsText: 'label',
@@ -789,6 +794,7 @@ ${ dashboard.layout_skeleton() }
     </div>
     <!-- ko if: $root.collection.getFacetById($parent.id()) -->
     <div data-bind="timelineChart: {datum: {counts: counts, extraSeries: (typeof extraSeries != 'undefined' ? extraSeries : []), widget_id: $parent.id(), label: label}, stacked: $root.collection.getFacetById($parent.id()).properties.stacked(), field: field, label: label, transformer: timelineChartDataTransformer,
+      type: $root.collection.getFacetById($parent.id()).properties.timelineChartType,
       fqs: $root.query.fqs,
       onSelectRange: function(from, to){ viewModel.collection.selectTimelineFacet({from: from, to: to, cat: field, widget_id: $parent.id()}) },
       onStateChange: function(state){ $root.collection.getFacetById($parent.id()).properties.stacked(state.stacked); },
@@ -1785,6 +1791,17 @@ $(document).ready(function () {
   }
 
   viewModel = new SearchViewModel(${ collection.get_c(user) | n,unicode }, _query, ${ initial | n,unicode });
+
+  viewModel.timelineChartTypes = ko.observableArray([
+    {
+      value: "line",
+      label: "${ _('Lines')}"
+    },
+    {
+      value: "bar",
+      label: "${ _('Bars')}"
+  }]);
+
   ko.applyBindings(viewModel);
 
   viewModel.init(function(data){

+ 51 - 24
desktop/core/src/desktop/static/desktop/js/ko.charts.js

@@ -124,13 +124,21 @@ ko.bindingHandlers.barChart = {
 
 ko.bindingHandlers.timelineChart = {
   update: function (element, valueAccessor) {
-    barChartBuilder(element, valueAccessor(), true);
+    if ($(element).find("svg").length > 0) {
+      $(element).find("svg").remove();
+    }
+    if (valueAccessor().type && valueAccessor().type() == "line"){
+      lineChartBuilder(element, valueAccessor(), true);
+    }
+    else {
+      barChartBuilder(element, valueAccessor(), true);
+    }
   }
 };
 
 ko.bindingHandlers.lineChart = {
   update: function (element, valueAccessor) {
-    lineChartBuilder(element, valueAccessor());
+    lineChartBuilder(element, valueAccessor(), false);
   }
 };
 
@@ -547,8 +555,23 @@ ko.bindingHandlers.scatterChart = {
   }
 };
 
+var insertLinebreaks = function (d, ref) {
+  var _el = d3.select(ref);
+  var _mom = moment(d);
+  if (_mom != null && _mom.isValid()) {
+    var _words = _mom.format("HH:mm:ss YYYY-MM-DD").split(" ");
+    _el.text("");
+    for (var i = 0; i < _words.length; i++) {
+      var tspan = _el.append("tspan").text(_words[i]);
+      if (i > 0) {
+        tspan.attr("x", 0).attr("dy", "15");
+      }
+    }
+  }
+};
+
 
-function lineChartBuilder(element, options) {
+function lineChartBuilder(element, options, isTimeline) {
   var _datum = options.transformer(options.datum);
   $(element).height(300);
   if ($(element).find("svg").length > 0 && (_datum.length == 0 || _datum[0].values.length == 0)) {
@@ -570,9 +593,17 @@ function lineChartBuilder(element, options) {
       }
       _chart.onSelectRange(function (from, to) {
         chartsUpdatingState();
-        options.onSelectRange(from, to);
+        options.onSelectRange($.isNumeric(from) ? new Date(moment(from).valueOf()) : from, $.isNumeric(to) ? new Date(moment(to).valueOf()) : to);
       });
       _chart.xAxis.showMaxMin(false);
+      if (isTimeline){
+        _chart.xAxis.tickFormat(function(d) { return d3.time.format("%Y-%m-%d %H:%M:%S")(new Date(d)); })
+        _chart.onChartUpdate(function () {
+          _d3.selectAll("g.nv-x.nv-axis g text").each(function (d){
+            insertLinebreaks(d, this);
+          });
+        });
+      }
 
       _chart.yAxis
           .tickFormat(d3.format(",0f"));
@@ -580,8 +611,16 @@ function lineChartBuilder(element, options) {
       var _d3 = ($(element).find("svg").length > 0) ? d3.select($(element).find("svg")[0]) : d3.select($(element)[0]).append("svg");
       _d3.datum(_datum)
           .transition().duration(150)
-          .each("end", options.onComplete != null ? options.onComplete : void(0))
-          .call(_chart);
+          .each("end", function () {
+            if (options.onComplete != null) {
+              options.onComplete();
+            }
+            if (isTimeline) {
+              _d3.selectAll("g.nv-x.nv-axis g text").each(function (d){
+                insertLinebreaks(d, this);
+              });
+            }
+          }).call(_chart);
 
       var _resizeTimeout = -1;
       nv.utils.windowResize(function () {
@@ -630,22 +669,6 @@ function barChartBuilder(element, options, isTimeline) {
     nv.addGraph(function () {
       var _chart;
 
-
-      var insertLinebreaks = function (d) {
-        var _el = d3.select(this);
-        var _mom = moment(d);
-        if (_mom != null && _mom.isValid()) {
-          var _words = _mom.format("HH:mm:ss YYYY-MM-DD").split(" ");
-          _el.text("");
-          for (var i = 0; i < _words.length; i++) {
-            var tspan = _el.append("tspan").text(_words[i]);
-            if (i > 0) {
-              tspan.attr("x", 0).attr("dy", "15");
-            }
-          }
-        }
-      };
-
       if (isTimeline) {
         if ($(element).find("svg").length > 0 && $(element).find(".nv-discreteBarWithAxes").length > 0) {
           $(element).find("svg").empty();
@@ -663,7 +686,9 @@ function barChartBuilder(element, options, isTimeline) {
         _chart.multibar.stacked(typeof options.stacked != "undefined" ? options.stacked : false);
         _chart.onStateChange(options.onStateChange);
         _chart.onChartUpdate(function () {
-          _d3.selectAll("g.nv-x.nv-axis g text").each(insertLinebreaks);
+          _d3.selectAll("g.nv-x.nv-axis g text").each(function (d){
+            insertLinebreaks(d, this);
+          });
         });
       }
       else {
@@ -735,7 +760,9 @@ function barChartBuilder(element, options, isTimeline) {
               options.onComplete();
             }
             if (isTimeline) {
-              _d3.selectAll("g.nv-x.nv-axis g text").each(insertLinebreaks);
+              _d3.selectAll("g.nv-x.nv-axis g text").each(function (d){
+                insertLinebreaks(d, this);
+              });
             }
           }).call(_chart);
 

+ 8 - 1
desktop/core/src/desktop/static/desktop/js/nv.d3.lineWithBrushChart.js

@@ -63,6 +63,7 @@ nv.models.lineWithBrushChart = function() {
     , selectionEnabled = false
     , onSelectRange = null
     , onStateChange = null
+    , onChartUpdate = null
     ;
 
   xAxis
@@ -107,7 +108,7 @@ nv.models.lineWithBrushChart = function() {
 
 
       chart.update = function() {
-        container.transition().duration(transitionDuration).call(chart)
+        container.transition().duration(transitionDuration).each("end", onChartUpdate).call(chart)
         if (selectionEnabled){
           enableBrush();
         }
@@ -613,6 +614,12 @@ nv.models.lineWithBrushChart = function() {
     return chart;
   };
 
+  chart.onChartUpdate = function(_) {
+    if (!arguments.length) return onChartUpdate;
+    onChartUpdate = _;
+    return chart;
+  };
+
   chart.onStateChange = function(_) {
     if (!arguments.length) return onStateChange;
     onStateChange = _;