]> source.dussan.org Git - sonarqube.git/commitdiff
Pie Chart mock
authorStas Vilchik <vilchiks@gmail.com>
Wed, 11 Dec 2013 09:30:16 +0000 (15:30 +0600)
committerStas Vilchik <vilchiks@gmail.com>
Wed, 11 Dec 2013 09:30:25 +0000 (15:30 +0600)
sonar-server/src/main/webapp/WEB-INF/app/controllers/mock/example_controller.rb
sonar-server/src/main/webapp/WEB-INF/app/views/layouts/_head.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/mock/example/pie_chart.html.erb [new file with mode: 0644]
sonar-server/src/main/webapp/javascripts/widgets/pie-chart.js [new file with mode: 0644]
sonar-server/src/main/webapp/stylesheets/style.css
sonar-server/wro.xml

index 0a3ce7fdd42d480ba6ef403c6b2e0e8a96f5fea2..a2ec5634dbbb938ce14850cf883e20bda3418454 100644 (file)
@@ -33,5 +33,9 @@ class Mock::ExampleController < Api::ApiController
         "foo": "bar"
       }
 RESPONSE
-    end
+  end
+
+  def pie_chart
+
+  end
 end
index 09c3d3152d4d44d26c6db5dbaaed5d1c9c539614..a1fd777877aaca6dce744f7224835d08c5db0fd5 100644 (file)
@@ -50,6 +50,7 @@
     <%= javascript_include_tag 'widgets/bubble-chart' %>
     <%= javascript_include_tag 'widgets/timeline' %>
     <%= javascript_include_tag 'widgets/stack-area' %>
+    <%= javascript_include_tag 'widgets/pie-chart' %>
 
     <%= javascript_include_tag 'select-list' %>
 
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/mock/example/pie_chart.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/mock/example/pie_chart.html.erb
new file mode 100644 (file)
index 0000000..f6dfdea
--- /dev/null
@@ -0,0 +1,80 @@
+<div id="pie-chart"></div>
+
+<script>
+  var pieChartData = [
+
+    {
+      key: 'org.codehaus.sonar:sonar-duplications:net.sourceforge.pmd.cpd.SourceCode',
+      name: 'SourceCode',
+      longName: 'net.sourceforge.pmd.cpd.SourceCode',
+      metric: 107.0,
+      metricFormatted: '107'
+    },
+
+    {
+      key: 'org.codehaus.sonar:sonar-duplications:net.sourceforge.pmd.cpd.TokenEntry',
+      name: 'TokenEntry',
+      longName: 'net.sourceforge.pmd.cpd.TokenEntry',
+      metric: 74.0,
+      metricFormatted: '74'
+    },
+
+    {
+      key: 'org.codehaus.sonar:sonar-duplications:net.sourceforge.pmd.cpd.Tokenizer',
+      name: 'Tokenizer',
+      longName: 'net.sourceforge.pmd.cpd.Tokenizer',
+      metric: 50.0,
+      metricFormatted: '50'
+    },
+
+    {
+      key: 'org.codehaus.sonar:sonar-duplications:net.sourceforge.pmd.cpd.Tokens',
+      name: 'Tokens',
+      longName: 'net.sourceforge.pmd.cpd.Tokens',
+      metric: 19.0,
+      metricFormatted: '19'
+    },
+
+    {
+      key: 'org.codehaus.sonar:sonar-deprecated:org.sonar.api.batch.AbstractCoverageExtension',
+      name: 'AbstractCoverageExtension',
+      longName: 'org.sonar.api.batch.AbstractCoverageExtension',
+      metric: 12.0,
+      metricFormatted: '12'
+    },
+
+    {
+      id: 3447,
+      key: 'org.codehaus.sonar:sonar-plugin-api:org.sonar.api.batch.AbstractSourceImporter',
+      name: 'AbstractSourceImporter',
+      longName: 'org.sonar.api.batch.AbstractSourceImporter',
+      metric: 70.0,
+      metricFormatted: '70'
+    },
+
+    {
+      key: 'org.codehaus.sonar:sonar-plugin-api:org.sonar.api.batch.AbstractSumChildrenDecorator',
+      name: 'AbstractSumChildrenDecorator',
+      longName: 'org.sonar.api.batch.AbstractSumChildrenDecorator',
+      metric: 35.0,
+      metricFormatted: '35'
+    },
+
+    {
+      key: 'org.codehaus.sonar:sonar-deprecated:org.sonar.api.batch.BatchExtensionDictionnary',
+      name: 'BatchExtensionDictionnary',
+      longName: 'org.sonar.api.batch.BatchExtensionDictionnary',
+      metric: 176.0,
+      metricFormatted: '176'
+    }
+  ];
+
+  var pieChart = new SonarWidgets.PieChart();
+  pieChart
+    .data(pieChartData)
+    .render('#pie-chart');
+
+  autoResize(500, function() {
+    pieChart.update('#pie-chart');
+  });
+</script>
diff --git a/sonar-server/src/main/webapp/javascripts/widgets/pie-chart.js b/sonar-server/src/main/webapp/javascripts/widgets/pie-chart.js
new file mode 100644 (file)
index 0000000..4bb174b
--- /dev/null
@@ -0,0 +1,275 @@
+/*global d3:false, baseUrl:false */
+/*jshint eqnull:true */
+
+window.SonarWidgets = window.SonarWidgets == null ? {} : window.SonarWidgets;
+
+(function () {
+
+  window.SonarWidgets.PieChart = function () {
+    // Set default values
+    this._data = [];
+    this._metrics = [];
+    this._width = window.SonarWidgets.PieChart.defaults.width;
+    this._height = window.SonarWidgets.PieChart.defaults.height;
+    this._margin = window.SonarWidgets.PieChart.defaults.margin;
+    this._legendWidth = window.SonarWidgets.PieChart.defaults.legendWidth;
+
+    this._lineHeight = 20;
+
+    // Export global variables
+    this.data = function (_) {
+      return param.call(this, '_data', _);
+    };
+
+    this.metrics = function (_) {
+      return param.call(this, '_metrics', _);
+    };
+
+    this.width = function (_) {
+      return param.call(this, '_width', _);
+    };
+
+    this.height = function (_) {
+      return param.call(this, '_height', _);
+    };
+
+    this.margin = function (_) {
+      return param.call(this, '_margin', _);
+    };
+
+    this.legendWidth = function (_) {
+      return param.call(this, '_legendWidth', _);
+    };
+  };
+
+  window.SonarWidgets.PieChart.prototype.render = function (container) {
+    var widget = this,
+        containerS = container;
+
+    container = d3.select(container);
+
+    this.width(container.property('offsetWidth'));
+
+    this.svg = container.append('svg')
+        .attr('class', 'sonar-d3');
+    this.gWrap = this.svg.append('g');
+
+    this.plotWrap = this.gWrap.append('g');
+
+    this.gWrap
+        .attr('transform', trans(this.margin().left, this.margin().top));
+
+
+    // Configure scales
+    this.color = d3.scale.category20();
+
+
+    // Configure arc
+    this.arc = d3.svg.arc()
+        .innerRadius(0);
+
+
+    // Configure pie
+    this.pie = d3.layout.pie()
+        .sort(null)
+        .value(function(d) { return d.metric; });
+
+
+    // Configure sectors
+    this.sectors = this.plotWrap.selectAll('.arc')
+        .data(this.pie(this.data()))
+        .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.pie(this.data()))
+        .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.data.name; });
+
+
+    // Configure details
+    this._detailsHeight = this._lineHeight * 4;
+
+    this.detailsWrap = this.gWrap.append('g')
+        .attr('width', this.legendWidth());
+
+    this.detailsColorIndicator = this.detailsWrap.append('rect')
+        .classed('details-color-indicator', true)
+        .attr('x', 0)
+        .attr('y', 0)
+        .attr('width', 4)
+        .attr('height', this._detailsHeight)
+        .style('opacity', 0);
+
+    this._detailsMetric = [
+      { name: 'Technical Dept', value: 8.5 },
+      { name: 'Lines of Code', value: 362 },
+      { name: 'Issues', value: 3 },
+      { name: 'Coverage', value: 86 }
+    ];
+
+
+    // Configure events
+    var enterHandler = function(sector, legend, 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 + ')');
+
+          updateMetrics(widget._detailsMetric);
+
+          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')
+              .text(function(d) { return d.name + ': ' + d.value; });
+
+          widget.detailsMetrics
+              .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')
+              .style('opacity', 1);
+        };
+
+    this.legends
+        .on('mouseenter', function(d, i) {
+          return enterHandler(widget.sectors[0][i], this, 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], i);
+        })
+        .on('mouseleave', function(d, i) {
+          return leaveHandler(this, widget.legends[0][i]);
+        });
+
+
+    // Update widget
+    this.update(containerS);
+
+    return this;
+  };
+
+
+
+  window.SonarWidgets.PieChart.prototype.update = function(container) {
+    container = d3.select(container);
+
+    var widget = this,
+        width = container.property('offsetWidth');
+    this.width(width > 100 ? width : 100);
+
+
+    // Update svg canvas
+    this.svg
+        .attr('width', this.width())
+        .attr('height', this.height());
+
+
+    // Update available size
+    this.availableWidth = this.width() - this.margin().left - this.margin().right - this.legendWidth();
+    this.availableHeight = this.height() - this.margin().top - this.margin().bottom;
+
+
+    // Update radius
+    this.radius = Math.min(this.availableWidth - this.legendWidth(), this.availableHeight) / 2;
+
+
+    // Update plot
+    this.plotWrap
+      .attr('transform', trans(this.radius, this.radius));
+
+
+    // Update arc
+    this.arc.outerRadius(this.radius);
+
+
+    // Update legend
+    this.legendWrap
+      .attr('transform', trans(20 + this.radius * 2, 0 ));
+
+
+    // Update details
+    this.detailsWrap
+        .attr('transform', trans(20 + this.radius * 2, this.availableHeight - this._detailsHeight ));
+
+
+    // Update sectors
+    this.sectors.selectAll('path')
+        .transition()
+        .attr('d', this.arc);
+
+    this.sectors.selectAll('text')
+        .attr('transform', function(d) { return 'translate(' + widget.arc.centroid(d) + ')'; });
+  };
+
+
+
+  window.SonarWidgets.PieChart.defaults = {
+    width: 350,
+    height: 300,
+    margin: { top: 10, right: 10, bottom: 10, left: 10 },
+    legendWidth: 250
+  };
+
+
+
+  // Some helper functions
+
+  // Gets or sets parameter
+  function param(name, value) {
+    if (value == null) {
+      return this[name];
+    } else {
+      this[name] = value;
+      return this;
+    }
+  }
+
+  // Helper for create the translate(x, y) string
+  function trans(left, top) {
+    return 'translate(' + left + ', ' + top + ')';
+  }
+
+})();
index c7830f16dce7fcae8433cc129ccea626f29ac31f..ef70b94a71608346d1793cfa670239f82c552b54 100644 (file)
@@ -2458,6 +2458,45 @@ textarea.width100 {
   opacity: 0.25;
 }
 
+.sonar-d3 .arc {
+  cursor: pointer;
+  transition: all 0.2s ease;
+}
+
+.sonar-d3 .arc-active {
+  -webkit-transform: scale(1.05);
+}
+
+.sonar-d3 .legend {
+  cursor: pointer;
+}
+
+.sonar-d3 .legend-bullet {
+  transition: all 0.2s ease;
+}
+
+.sonar-d3 .legend-text {
+  font-size: 11px;
+}
+
+.sonar-d3 .legend-active .legend-bullet {
+  -webkit-transform: scale(1.4);
+  -webkit-transform-origin: center;
+}
+
+.sonar-d3 .details-color-indicator {
+  fill: #fff;
+  transition: all 0.2s ease;
+}
+
+.sonar-d3 .details-metric {
+  font-size: 11px;
+}
+
+.sonar-d3 .details-metric-main {
+  font-weight: bold;
+}
+
 .sonar-d3 .info {
 
 }
index 215716a06c4e6a9087ffa68408da9b4ec19c5ba7..11c1ba2ebe4c2ee28274491f2f3b37e5cd002edd 100644 (file)
@@ -30,6 +30,7 @@
     <js>/javascripts/widgets/bubble-chart.js</js>
     <js>/javascripts/widgets/timeline.js</js>
     <js>/javascripts/widgets/stack-area.js</js>
+    <js>/javascripts/widgets/pie-chart.js</js>
 
     <js>/javascripts/select-list.js</js>