]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-4952 Provide a new PieChart widget to display a measure filter
authorStas Vilchik <vilchiks@gmail.com>
Fri, 13 Dec 2013 06:47:15 +0000 (12:47 +0600)
committerStas Vilchik <vilchiks@gmail.com>
Fri, 13 Dec 2013 06:47:15 +0000 (12:47 +0600)
Convert to donut chart, update layout

plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/pie_chart.html.erb
sonar-server/src/main/webapp/javascripts/widgets/pie-chart.js
sonar-server/src/main/webapp/stylesheets/style.css

index 04f414a5465868896355223cd95152194d0b875f..2e9ae043948f311c722cf718284da88e7b7859f4 100644 (file)
   (function () {
     var metrics = [
           '<%= widget_properties["mainMetric"].name %>',
-          '<%= widget_properties["extraMetric1"].name %>',
-          '<%= widget_properties["extraMetric2"].name %>'
+          '<%= widget_properties["extraMetric1"].name %>'
+          <% if (widget_properties["extraMetric2"]) %>
+          , '<%= widget_properties["extraMetric2"].name %>'
+          <% end %>
         ],
         query = [
           'filter=<%= filterId %>',
           'metrics=' + metrics.join(','),
           'fields=name',
-          'pageSize=9',
+          'pageSize=10',
           'page=1',
           'sort=metric:' + metrics[0],
           'asc=false'
index 254b7db6ea9b48fb72772c55fc4f4e1e4d4377b9..90f799d0607cd60ad1b909c7301d1cfaa342d1f7 100644 (file)
@@ -14,6 +14,8 @@ window.SonarWidgets = window.SonarWidgets == null ? {} : window.SonarWidgets;
     this._height = window.SonarWidgets.PieChart.defaults.height;
     this._margin = window.SonarWidgets.PieChart.defaults.margin;
     this._legendWidth = window.SonarWidgets.PieChart.defaults.legendWidth;
+    this._legendMargin = window.SonarWidgets.PieChart.defaults.legendMargin;
+    this._detailsWidth = window.SonarWidgets.PieChart.defaults.detailsWidth;
 
     this._lineHeight = 20;
 
@@ -46,6 +48,14 @@ window.SonarWidgets = window.SonarWidgets == null ? {} : window.SonarWidgets;
     this.legendWidth = function (_) {
       return param.call(this, '_legendWidth', _);
     };
+
+    this.legendMargin = function (_) {
+      return param.call(this, '_legendMargin', _);
+    };
+
+    this.detailsWidth = function (_) {
+      return param.call(this, '_detailsWidth', _);
+    };
   };
 
   window.SonarWidgets.PieChart.prototype.render = function (container) {
@@ -60,7 +70,8 @@ window.SonarWidgets = window.SonarWidgets == null ? {} : window.SonarWidgets;
         .attr('class', 'sonar-d3');
     this.gWrap = this.svg.append('g');
 
-    this.plotWrap = this.gWrap.append('g');
+    this.plotWrap = this.gWrap.append('g')
+        .classed('plot', true);
 
     this.gWrap
         .attr('transform', trans(this.margin().left, this.margin().top));
@@ -71,10 +82,22 @@ window.SonarWidgets = window.SonarWidgets == null ? {} : window.SonarWidgets;
     this.getMainMetric = function(d) {
       return d.measures[widget.mainMetric].val;
     };
+    this.fm = function(value, name) {
+      var type = this.metrics()[name].type;
+
+      switch (type) {
+        case 'FLOAT':
+          return d3.format('.1f')(value);
+        case 'INT':
+          return d3.format('d')(value);
+        default :
+          return value;
+      }
+    };
 
 
     // Configure scales
-    this.color = d3.scale.category20();
+    this.color = d3.scale.category10();
 
 
     // Configure arc
@@ -88,39 +111,9 @@ window.SonarWidgets = window.SonarWidgets == null ? {} : window.SonarWidgets;
         .value(function(d) { return widget.getMainMetric(d); });
 
 
-    // Configure sectors
-    this.sectors = this.plotWrap.selectAll('.arc')
-        .data(this.pie(this.components()))
-        .enter().append('g').attr('class', 'arc');
-
-    this.sectors.append('path')
-        .style('fill', function(d, i) { return widget.color(i); });
-
-
-    // Configure legend
-    this.legendWrap = this.gWrap.append('g')
-        .attr('width', this.legendWidth());
-
-    this.legends = this.legendWrap.selectAll('.legend')
-        .data(this.components());
-
-    this.legends.enter().append('g')
-        .attr('class', 'legend')
-        .attr('transform', function(d, i) { return trans(0, 10 + i * widget._lineHeight); });
-
-    this.legends.append('circle')
-        .attr('class', 'legend-bullet')
-        .attr('r', 4)
-        .style('fill', function(d, i) { return widget.color(i); });
-
-    this.legends.append('text')
-        .attr('class', 'legend-text')
-        .attr('transform', trans(10, 3))
-        .text(function(d) { return d.name; });
-
-
     // Configure details
-    this._detailsHeight = this._lineHeight * 4;
+    this._metricsCount = Object.keys(this.metrics()).length + 1;
+    this._detailsHeight = this._lineHeight * this._metricsCount;
 
     this.detailsWrap = this.gWrap.append('g')
         .attr('width', this.legendWidth());
@@ -134,73 +127,10 @@ window.SonarWidgets = window.SonarWidgets == null ? {} : window.SonarWidgets;
         .attr('height', this._detailsHeight)
         .style('opacity', 0);
 
-
-    // Configure events
-    var enterHandler = function(sector, legend, d, i) {
-          var scaleFactor = (widget.radius + 5) / widget.radius;
-          d3.select(legend)
-              .classed('legend-active', true);
-          d3.select(sector)
-              .classed('arc-active', true)
-              .style('-webkit-transform', 'scale(' + scaleFactor + ')');
-
-          var metrics = widget.metricsPriority().map(function(m) {
-            return {
-              name: widget.metrics()[m].name,
-              value: d.measures[m].val
-            };
-          });
-          updateMetrics(metrics);
-
-          widget.detailsColorIndicator
-              .style('opacity', 1)
-              .style('fill', widget.color(i));
-        },
-
-        leaveHandler = function(sector, legend) {
-          d3.select(legend).classed('legend-active', false);
-          d3.select(sector)
-              .classed('arc-active', false)
-              .style('-webkit-transform', 'scale(1)');
-          widget.detailsColorIndicator
-              .style('opacity', 0);
-          widget.detailsMetrics
-              .style('opacity', 0);
-        },
-
-        updateMetrics = function(metrics) {
-
-          widget.detailsMetrics = widget.detailsWrap.selectAll('.details-metric')
-              .data(metrics);
-
-          widget.detailsMetrics.enter().append('text')
-              .classed('details-metric', true)
-              .classed('details-metric-main', function(d, i) { return i === 0; })
-              .attr('transform', function(d, i) { return trans(10, i * widget._lineHeight); })
-              .attr('dy', '1.2em');
-
-          widget.detailsMetrics
-              .text(function(d) { return d.name + ': ' + d.value; })
-              .style('opacity', 1);
-
-          widget.detailsMetrics.exit().remove();
-        };
-
-    this.legends
-        .on('mouseenter', function(d, i) {
-          return enterHandler(widget.sectors[0][i], this, d, i);
-        })
-        .on('mouseleave', function(d, i) {
-          return leaveHandler(widget.sectors[0][i], this);
-        });
-
-    this.sectors
-        .on('mouseenter', function(d, i) {
-          return enterHandler(this, widget.legends[0][i], d.data, i);
-        })
-        .on('mouseleave', function(d, i) {
-          return leaveHandler(this, widget.legends[0][i]);
-        });
+    this.donutLabel = this.plotWrap.append('text')
+        .attr('dy', '0.35em')
+        .style('text-anchor', 'middle')
+        .style('opacity', 0);
 
 
     // Update widget
@@ -226,11 +156,9 @@ window.SonarWidgets = window.SonarWidgets == null ? {} : window.SonarWidgets;
 
 
     // Update available size
-    this.availableWidth = this.width() - this.margin().left - this.margin().right - this.legendWidth();
+    this.availableWidth = this.width() - this.margin().left - this.margin().right -
+        this.legendWidth() - this.legendMargin();
     this.availableHeight = this.height() - this.margin().top - this.margin().bottom;
-
-
-    // Update radius
     this.radius = Math.min(this.availableWidth, this.availableHeight) / 2;
 
 
@@ -241,23 +169,93 @@ window.SonarWidgets = window.SonarWidgets == null ? {} : window.SonarWidgets;
 
     // Update arc
     this.arc
+        .innerRadius(this.radius / 2)
         .outerRadius(this.radius);
 
 
-    // Update legend
-    this.legendWrap
-        .attr('transform', trans(20 + this.radius * 2, 0 ));
+    // Configure sectors
+    this.sectors = this.plotWrap.selectAll('.arc')
+        .data(this.pie(this.components()));
+
+    this.sectors
+        .enter()
+        .append('path')
+        .classed('arc', true)
+        .style('fill', function(d, i) { return widget.color(i); });
+
+    this.sectors
+        .transition()
+        .attr('d', this.arc);
+
+    this.sectors
+        .exit().remove();
 
 
     // Update details
     this.detailsWrap
-        .attr('transform', trans(20 + this.radius * 2, this.availableHeight - this._detailsHeight ));
+        .attr('width', this.legendWidth())
+        .attr('transform', trans(
+            this.legendMargin() + 2 * this.radius, this.radius - this._detailsHeight / 2
+        ));
 
-
-    // Update sectors
-    this.sectors.selectAll('path')
+    this.donutLabel
         .transition()
-        .attr('d', this.arc);
+        .style('font-size', (this.radius / 6) + 'px');
+
+
+    // Configure events
+    var enterHandler = function(sector, d, i) {
+          var metrics = widget.metricsPriority().map(function(m) {
+            return {
+              name: widget.metrics()[m].name,
+              value: widget.fm(d.measures[m].val, m)
+            };
+          });
+          metrics.unshift({ name: d.name });
+          updateMetrics(metrics);
+
+          widget.donutLabel
+              .style('opacity', 1)
+              .text(widget.fm(widget.getMainMetric(d), widget.mainMetric));
+
+          widget.detailsColorIndicator
+              .style('opacity', 1)
+              .style('fill', widget.color(i));
+        },
+
+        leaveHandler = function() {
+          widget.detailsColorIndicator
+              .style('opacity', 0);
+          widget.detailsMetrics
+              .style('opacity', 0);
+          widget.donutLabel
+              .style('opacity', 0)
+              .text('');
+        },
+
+        updateMetrics = function(metrics) {
+
+          widget.detailsMetrics = widget.detailsWrap.selectAll('.details-metric')
+              .data(metrics);
+
+          widget.detailsMetrics.enter().append('text')
+              .classed('details-metric', true)
+              .classed('details-metric-main', function(d, i) { return i === 0; })
+              .attr('transform', function(d, i) { return trans(10, i * widget._lineHeight); })
+              .attr('dy', '1.2em');
+
+          widget.detailsMetrics
+              .text(function(d) { return d.name + (d.value ? ': ' + d.value : ''); })
+              .style('opacity', 1);
+
+          widget.detailsMetrics.exit().remove();
+        };
+
+    this.sectors
+        .on('mouseenter', function(d, i) {
+          return enterHandler(this, d.data, i);
+        })
+        .on('mouseleave', leaveHandler);
   };
 
 
@@ -266,7 +264,8 @@ window.SonarWidgets = window.SonarWidgets == null ? {} : window.SonarWidgets;
     width: 350,
     height: 300,
     margin: { top: 10, right: 10, bottom: 10, left: 10 },
-    legendWidth: 250
+    legendWidth: 160,
+    legendMargin: 30
   };
 
 
index ef70b94a71608346d1793cfa670239f82c552b54..a5150e840ed5da0d61206587d8ea2d045bc87d69 100644 (file)
@@ -2440,6 +2440,18 @@ textarea.width100 {
   fill: #444;
 }
 
+.sonar-d3 .plot {
+  transition: all 0.2s ease;
+}
+
+.sonar-d3 .plot:hover .arc {
+  opacity: 0.4;
+}
+
+.sonar-d3 .plot .arc:hover {
+  opacity: 1;
+}
+
 .sonar-d3 .plot .line {
   fill: none;
   stroke: #000;
@@ -2460,13 +2472,11 @@ textarea.width100 {
 
 .sonar-d3 .arc {
   cursor: pointer;
+  stroke: #fff;
+  stroke-width: 1px;
   transition: all 0.2s ease;
 }
 
-.sonar-d3 .arc-active {
-  -webkit-transform: scale(1.05);
-}
-
 .sonar-d3 .legend {
   cursor: pointer;
 }