aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/widgets
diff options
context:
space:
mode:
authorStas Vilchik <vilchiks@gmail.com>2015-05-18 16:29:19 +0200
committerStas Vilchik <vilchiks@gmail.com>2015-05-19 18:20:09 +0200
commite59e4aa2c06a57566f148f4217d286461231ae58 (patch)
treead0918eb06b2474a6c71997b7ff573bbb93e0170 /server/sonar-web/src/main/js/widgets
parent8d82c9cf9ba88c1517604b4063ad0fc2a9a1bb9a (diff)
downloadsonarqube-e59e4aa2c06a57566f148f4217d286461231ae58.tar.gz
sonarqube-e59e4aa2c06a57566f148f4217d286461231ae58.zip
change web structure: separate components
Diffstat (limited to 'server/sonar-web/src/main/js/widgets')
-rw-r--r--server/sonar-web/src/main/js/widgets/bubble-chart.js541
-rw-r--r--server/sonar-web/src/main/js/widgets/issue-filter/templates/_widget-issue-filter-limit.hbs1
-rw-r--r--server/sonar-web/src/main/js/widgets/issue-filter/templates/_widget-issue-filter-total.hbs11
-rw-r--r--server/sonar-web/src/main/js/widgets/issue-filter/templates/widget-issue-filter-action-plans.hbs26
-rw-r--r--server/sonar-web/src/main/js/widgets/issue-filter/templates/widget-issue-filter-assignees.hbs26
-rw-r--r--server/sonar-web/src/main/js/widgets/issue-filter/templates/widget-issue-filter-resolutions.hbs26
-rw-r--r--server/sonar-web/src/main/js/widgets/issue-filter/templates/widget-issue-filter-severities.hbs23
-rw-r--r--server/sonar-web/src/main/js/widgets/issue-filter/templates/widget-issue-filter-statuses.hbs23
-rw-r--r--server/sonar-web/src/main/js/widgets/issue-filter/templates/widget-issue-filter.hbs22
-rw-r--r--server/sonar-web/src/main/js/widgets/issue-filter/widget.js (renamed from server/sonar-web/src/main/js/widgets/issue-filter.js)2
-rw-r--r--server/sonar-web/src/main/js/widgets/pie-chart.js417
-rw-r--r--server/sonar-web/src/main/js/widgets/stack-area.js404
-rw-r--r--server/sonar-web/src/main/js/widgets/timeline.js417
-rw-r--r--server/sonar-web/src/main/js/widgets/widget.js120
14 files changed, 159 insertions, 1900 deletions
diff --git a/server/sonar-web/src/main/js/widgets/bubble-chart.js b/server/sonar-web/src/main/js/widgets/bubble-chart.js
deleted file mode 100644
index fc166404423..00000000000
--- a/server/sonar-web/src/main/js/widgets/bubble-chart.js
+++ /dev/null
@@ -1,541 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-/*global d3:false, baseUrl:false */
-
-window.SonarWidgets = window.SonarWidgets == null ? {} : window.SonarWidgets;
-
-(function () {
-
- window.SonarWidgets.BubbleChart = function () {
- // Set default values
- this._components = [];
- this._metrics = [];
- this._metricsPriority = [];
- this._width = window.SonarWidgets.BubbleChart.defaults.width;
- this._height = window.SonarWidgets.BubbleChart.defaults.height;
- this._margin = window.SonarWidgets.BubbleChart.defaults.margin;
- this._xLog = window.SonarWidgets.BubbleChart.defaults.xLog;
- this._yLog = window.SonarWidgets.BubbleChart.defaults.yLog;
- this._bubbleColor = window.SonarWidgets.BubbleChart.defaults.bubbleColor;
- this._bubbleColorUndefined = window.SonarWidgets.BubbleChart.defaults.bubbleColorUndefined;
- this._options = {};
-
- // Export global variables
- this.metrics = function (_) {
- return param.call(this, '_metrics', _);
- };
-
- this.metricsPriority = function (_) {
- return param.call(this, '_metricsPriority', _);
- };
-
- this.components = function (_) {
- return param.call(this, '_components', _);
- };
-
- 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.xLog = function (_) {
- return param.call(this, '_xLog', _);
- };
-
- this.yLog = function (_) {
- return param.call(this, '_yLog', _);
- };
-
- this.bubbleColor = function (_) {
- return param.call(this, '_bubbleColor', _);
- };
-
- this.bubbleColorUndefined = function (_) {
- return param.call(this, '_bubbleColorUndefined', _);
- };
-
- this.options = function (_) {
- return param.call(this, '_options', _);
- };
- };
-
-
- window.SonarWidgets.BubbleChart.prototype.hasValidData = function () {
- var widget = this,
- noInvalidEntry = true,
- atLeastOneValueOnX = false,
- atLeastOneValueOnY = false;
- this.components().forEach(function(component) {
- noInvalidEntry = noInvalidEntry &&
- !!component.measures[widget.metricsPriority()[0]] &&
- !!component.measures[widget.metricsPriority()[1]];
- atLeastOneValueOnX = atLeastOneValueOnX ||
- (component.measures[widget.metricsPriority()[0]] || {}).fval !== '-';
- atLeastOneValueOnY = atLeastOneValueOnY ||
- (component.measures[widget.metricsPriority()[1]] || {}).fval !== '-';
- });
- return !!noInvalidEntry && !!atLeastOneValueOnX && !!atLeastOneValueOnY;
- };
-
-
- window.SonarWidgets.BubbleChart.prototype.init = function (container) {
- this.width(container.property('offsetWidth'));
-
- this.svg = container.append('svg')
- .attr('class', 'sonar-d3');
- this.gWrap = this.svg.append('g');
-
- this.gxAxis = this.gWrap.append('g');
- this.gyAxis = this.gWrap.append('g');
-
- this.gGrid = this.gWrap.append('g');
- this.gxGrid = this.gGrid.append('g');
- this.gyGrid = this.gGrid.append('g');
-
- this.plotWrap = this.gWrap.append('g');
-
- this.infoWrap = this.gWrap.append('g');
- this.infoDate = this.infoWrap.append('text');
-
- this.gWrap
- .attr('transform', trans(this.margin().left, this.margin().top));
- };
-
-
- window.SonarWidgets.BubbleChart.prototype.initMetrics = function () {
- var widget = this;
-
- this.xMetric = this.metricsPriority()[0];
- this.getXMetric = function(d) {
- return d.measures[widget.xMetric].val;
- };
-
- this.yMetric = this.metricsPriority()[1];
- this.getYMetric = function(d) {
- return d.measures[widget.yMetric].val;
- };
-
- this.sizeMetric = this.metricsPriority()[2];
- this.getSizeMetric = function(d) {
- return !!d.measures[widget.sizeMetric] ? d.measures[widget.sizeMetric].val : 0;
- };
- };
-
-
- window.SonarWidgets.BubbleChart.prototype.initScales = function () {
- var widget = this;
- this
- .xLog(this.options().xLog)
- .yLog(this.options().yLog);
-
- this.x = this.xLog() ? d3.scale.log() : d3.scale.linear();
- this.y = this.yLog() ? d3.scale.log() : d3.scale.linear();
- this.size = d3.scale.linear();
-
- this.x.range([0, this.availableWidth]);
- this.y.range([this.availableHeight, 0]);
- this.size.range([5, 45]);
-
- if (this.components().length > 1) {
- this.x.domain(d3.extent(this.components(), function (d) {
- return widget.getXMetric(d);
- }));
- this.y.domain(d3.extent(this.components(), function (d) {
- return widget.getYMetric(d);
- }));
- this.size.domain(d3.extent(this.components(), function (d) {
- return widget.getSizeMetric(d);
- }));
- } else {
- var singleComponent = this.components()[0],
- xm = this.getXMetric(singleComponent),
- ym = this.getYMetric(singleComponent),
- sm = this.getSizeMetric(singleComponent);
- this.x.domain([xm * 0.8, xm * 1.2]);
- this.y.domain([ym * 0.8, ym * 1.2]);
- this.size.domain([sm * 0.8, sm * 1.2]);
- }
- };
-
-
- window.SonarWidgets.BubbleChart.prototype.initBubbles = function () {
- var widget = this;
-
- // Create bubbles
- this.items = this.plotWrap.selectAll('.item')
- .data(this.components());
-
-
- // Render bubbles
- this.items.enter().append('g')
- .attr('class', 'item')
- .attr('name', function (d) {
- return d.longName;
- })
- .style('cursor', 'pointer')
- .append('circle')
- .attr('r', function (d) {
- return widget.size(widget.getSizeMetric(d));
- })
- .style('fill', function () {
- return widget.bubbleColor();
- })
- .style('fill-opacity', 0.2)
- .style('stroke', function () {
- return widget.bubbleColor();
- })
- .style('transition', 'all 0.2s ease')
-
- .attr('title', function (d) {
- var xMetricName = widget.metrics()[widget.xMetric].name,
- yMetricName = widget.metrics()[widget.yMetric].name,
- sizeMetricName = widget.metrics()[widget.sizeMetric].name,
-
- xMetricValue = d.measures[widget.xMetric].fval,
- yMetricValue = d.measures[widget.yMetric].fval,
- sizeMetricValue = d.measures[widget.sizeMetric].fval;
-
- return '<div class="text-left">' +
- collapsedDirFromPath(d.longName) + '<br>' +
- fileFromPath(d.longName) + '<br>' + '<br>' +
- xMetricName + ': ' + xMetricValue + '<br>' +
- yMetricName + ': ' + yMetricValue + '<br>' +
- sizeMetricName + ': ' + sizeMetricValue +
- '</div>';
- })
- .attr('data-placement', 'bottom')
- .attr('data-toggle', 'tooltip');
-
- this.items.exit().remove();
-
- this.items.sort(function (a, b) {
- return widget.getSizeMetric(b) - widget.getSizeMetric(a);
- });
- };
-
-
- window.SonarWidgets.BubbleChart.prototype.initBubbleEvents = function () {
- var widget = this;
- this.items
- .on('click', function (d) {
- window.location = widget.options().baseUrl + '?id=' + encodeURIComponent(d.key);
- })
- .on('mouseenter', function () {
- d3.select(this).select('circle')
- .style('fill-opacity', 0.8);
- })
- .on('mouseleave', function () {
- d3.select(this).select('circle')
- .style('fill-opacity', 0.2);
- });
- };
-
-
- window.SonarWidgets.BubbleChart.prototype.initAxes = function () {
- // X
- this.xAxis = d3.svg.axis()
- .scale(this.x)
- .orient('bottom');
-
- this.gxAxisLabel = this.gxAxis.append('text')
- .text(this.metrics()[this.xMetric].name)
- .style('font-weight', 'bold')
- .style('text-anchor', 'middle');
-
-
- // Y
- this.yAxis = d3.svg.axis()
- .scale(this.y)
- .orient('left');
-
- this.gyAxis.attr('transform', trans(60 - this.margin().left, 0));
-
- this.gyAxisLabel = this.gyAxis.append('text')
- .text(this.metrics()[this.yMetric].name)
- .style('font-weight', 'bold')
- .style('text-anchor', 'middle');
- };
-
-
- window.SonarWidgets.BubbleChart.prototype.initGrid = function () {
- this.gxGridLines = this.gxGrid.selectAll('line').data(this.x.ticks()).enter()
- .append('line');
-
- this.gyGridLines = this.gyGrid.selectAll('line').data(this.y.ticks()).enter()
- .append('line');
-
- this.gGrid.selectAll('line')
- .style('stroke', '#000')
- .style('stroke-opacity', 0.25);
- };
-
-
- window.SonarWidgets.BubbleChart.prototype.render = function (container) {
- var containerS = container;
-
- container = d3.select(container);
-
- if (!this.hasValidData()) {
- container.text(this.options().noMainMetric);
- return;
- }
-
- this.init(container);
- this.initMetrics();
- this.initScales();
- this.initBubbles();
- this.initBubbleEvents();
- this.initAxes();
- this.initGrid();
- this.update(containerS);
-
- jQuery('[data-toggle="tooltip"]').tooltip({ container: 'body', html: true });
-
- return this;
- };
-
-
- window.SonarWidgets.BubbleChart.prototype.adjustScalesAfterUpdate = function () {
- var widget = this;
- // X
- var minX = d3.min(this.components(), function (d) {
- return widget.x(widget.getXMetric(d)) - widget.size(widget.getSizeMetric(d));
- }),
- maxX = d3.max(this.components(), function (d) {
- return widget.x(widget.getXMetric(d)) + widget.size(widget.getSizeMetric(d));
- }),
- dMinX = minX < 0 ? this.x.range()[0] - minX : this.x.range()[0],
- dMaxX = maxX > this.x.range()[1] ? maxX - this.x.range()[1] : 0;
- this.x.range([dMinX, this.availableWidth - dMaxX]);
-
- // Y
- var minY = d3.min(this.components(), function (d) {
- return widget.y(widget.getYMetric(d)) - widget.size(widget.getSizeMetric(d));
- }),
- maxY = d3.max(this.components(), function (d) {
- return widget.y(widget.getYMetric(d)) + widget.size(widget.getSizeMetric(d));
- }),
- dMinY = minY < 0 ? this.y.range()[1] - minY: this.y.range()[1],
- dMaxY = maxY > this.y.range()[0] ? maxY - this.y.range()[0] : 0;
- this.y.range([this.availableHeight - dMaxY, dMinY]);
-
-
- // Format improvement for log scales
- // X
- if (this.xLog()) {
- this.xAxis.tickFormat(function (d) {
- var ticksCount = widget.availableWidth / 50;
- return widget.x.tickFormat(ticksCount, d3.format(',d'))(d);
- });
- }
-
- // Y
- if (this.yLog()) {
- this.yAxis.tickFormat(function (d) {
- var ticksCount = widget.availableHeight / 30;
- return widget.y.tickFormat(ticksCount, d3.format(',d'))(d);
- });
- }
-
- // Make scale's domains nice
- this.x.nice();
- this.y.nice();
- };
-
-
- window.SonarWidgets.BubbleChart.prototype.updateScales = function () {
- var widget = this;
- this.x.range([0, this.availableWidth]);
- this.y.range([this.availableHeight, 0]);
-
- if (this.components().length > 1) {
- this.x.domain(d3.extent(this.components(), function (d) {
- return widget.getXMetric(d);
- }));
- this.y.domain(d3.extent(this.components(), function (d) {
- return widget.getYMetric(d);
- }));
- } else {
- var singleComponent = this.components()[0],
- xm = this.getXMetric(singleComponent),
- ym = this.getYMetric(singleComponent),
- sm = this.getSizeMetric(singleComponent);
- this.x.domain([xm * 0.8, xm * 1.2]);
- this.y.domain([ym * 0.8, ym * 1.2]);
- this.size.domain([sm * 0.8, sm * 1.2]);
- }
-
- if (this.x.domain()[0] === 0 && this.x.domain()[1] === 0) {
- this.x.domain([0, 1]);
- }
- if (this.y.domain()[0] === 0 && this.y.domain()[1] === 0) {
- this.y.domain([0, 1]);
- }
-
- // Avoid zero values when using log scale
- if (this.xLog) {
- var xDomain = this.x.domain();
- this.x
- .domain([xDomain[0] > 0 ? xDomain[0] : 0.1, xDomain[1]])
- .clamp(true);
- }
-
- if (this.yLog) {
- var yDomain = this.y.domain();
- this.y
- .domain([yDomain[0] > 0 ? yDomain[0] : 0.1, yDomain[1]])
- .clamp(true);
- }
- };
-
-
- window.SonarWidgets.BubbleChart.prototype.updateBubbles = function () {
- var widget = this;
- this.items
- .transition()
- .attr('transform', function (d) {
- return trans(widget.x(widget.getXMetric(d)), widget.y(widget.getYMetric(d)));
- });
- };
-
-
- window.SonarWidgets.BubbleChart.prototype.updateAxes = function () {
- // X
- this.gxAxis.attr('transform', trans(0, this.availableHeight + this.margin().bottom - 40));
-
- this.gxAxis.transition().call(this.xAxis);
-
- this.gxAxis.selectAll('path')
- .style('fill', 'none')
- .style('stroke', '#444');
-
- this.gxAxis.selectAll('text')
- .style('fill', '#444');
-
- this.gxAxisLabel
- .attr('transform', trans(this.availableWidth / 2, 35));
-
- // Y
- this.gyAxis.transition().call(this.yAxis);
-
- this.gyAxis.selectAll('path')
- .style('fill', 'none')
- .style('stroke', '#444');
-
- this.gyAxis.selectAll('text')
- .style('fill', '#444');
-
- this.gyAxisLabel
- .attr('transform', trans(-45, this.availableHeight / 2) + ' rotate(-90)');
- };
-
-
- window.SonarWidgets.BubbleChart.prototype.updateGrid = function () {
- var widget = this;
- this.gxGridLines
- .transition()
- .attr({
- x1: function (d) {
- return widget.x(d);
- },
- x2: function (d) {
- return widget.x(d);
- },
- y1: widget.y.range()[0],
- y2: widget.y.range()[1]
- });
-
- this.gyGridLines
- .transition()
- .attr({
- x1: widget.x.range()[0],
- x2: widget.x.range()[1],
- y1: function (d) {
- return widget.y(d);
- },
- y2: function (d) {
- return widget.y(d);
- }
- });
- };
-
-
- window.SonarWidgets.BubbleChart.prototype.update = function (container) {
- container = d3.select(container);
-
- var 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.availableHeight = this.height() - this.margin().top - this.margin().bottom;
-
- this.updateScales();
- this.adjustScalesAfterUpdate();
- this.updateBubbles();
- this.updateAxes();
- this.updateGrid();
- };
-
-
-
- window.SonarWidgets.BubbleChart.defaults = {
- width: 350,
- height: 150,
- margin: { top: 10, right: 10, bottom: 50, left: 70 },
- xLog: false,
- yLog: false,
- bubbleColor: '#4b9fd5',
- bubbleColorUndefined: '#b3b3b3'
- };
-
-
-
- // 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 + ')';
- }
-
-})();
diff --git a/server/sonar-web/src/main/js/widgets/issue-filter/templates/_widget-issue-filter-limit.hbs b/server/sonar-web/src/main/js/widgets/issue-filter/templates/_widget-issue-filter-limit.hbs
new file mode 100644
index 00000000000..6da82834180
--- /dev/null
+++ b/server/sonar-web/src/main/js/widgets/issue-filter/templates/_widget-issue-filter-limit.hbs
@@ -0,0 +1 @@
+<div class="note text-center spacer-top">{{tp 'max_items_reached' maxResults}}</div>
diff --git a/server/sonar-web/src/main/js/widgets/issue-filter/templates/_widget-issue-filter-total.hbs b/server/sonar-web/src/main/js/widgets/issue-filter/templates/_widget-issue-filter-total.hbs
new file mode 100644
index 00000000000..03fb4134f4a
--- /dev/null
+++ b/server/sonar-web/src/main/js/widgets/issue-filter/templates/_widget-issue-filter-total.hbs
@@ -0,0 +1,11 @@
+<tr>
+ <td>
+ <a href="{{issueFilterTotalLink parsedQuery}}"><strong>{{t 'total'}}</strong></a>
+ </td>
+ <td class="text-right"><strong>{{#notNull periodDate}}+{{/notNull}}{{numberShort total}}</strong></td>
+ <td class="barchart">
+ <div class="barchart" style="width: 100%;">
+ <div style="width: 100%;"></div>
+ </div>
+ </td>
+</tr>
diff --git a/server/sonar-web/src/main/js/widgets/issue-filter/templates/widget-issue-filter-action-plans.hbs b/server/sonar-web/src/main/js/widgets/issue-filter/templates/widget-issue-filter-action-plans.hbs
new file mode 100644
index 00000000000..07c9b17f40c
--- /dev/null
+++ b/server/sonar-web/src/main/js/widgets/issue-filter/templates/widget-issue-filter-action-plans.hbs
@@ -0,0 +1,26 @@
+<table class="data zebra">
+ {{> '_widget-issue-filter-total'}}
+ {{#each items}}
+ <tr>
+ <td>
+ {{#eq val ''}}
+ <a href="{{issueFilterItemLink ../../parsedQuery 'planned' 'false'}}">{{t 'issue.unplanned'}}</a>
+ {{else}}
+ <a href="{{issueFilterItemLink ../../parsedQuery 'actionPlans' val}}">{{default label val}}</a>
+ {{/eq}}
+ </td>
+ <td class="text-right nowrap">
+ {{#notNull ../periodDate}}+{{/notNull}}{{numberShort count}}
+ </td>
+ <td class="barchart">
+ <div class="barchart" style="width: 100%;">
+ <div style="width: {{percent count ../total}};"></div>
+ </div>
+ </td>
+ </tr>
+ {{/each}}
+</table>
+
+{{#if maxResultsReached}}
+ {{> '_widget-issue-filter-limit'}}
+{{/if}}
diff --git a/server/sonar-web/src/main/js/widgets/issue-filter/templates/widget-issue-filter-assignees.hbs b/server/sonar-web/src/main/js/widgets/issue-filter/templates/widget-issue-filter-assignees.hbs
new file mode 100644
index 00000000000..494104f3ee9
--- /dev/null
+++ b/server/sonar-web/src/main/js/widgets/issue-filter/templates/widget-issue-filter-assignees.hbs
@@ -0,0 +1,26 @@
+<table class="data zebra">
+ {{> '_widget-issue-filter-total'}}
+ {{#each items}}
+ <tr>
+ <td>
+ {{#eq val ''}}
+ <a href="{{issueFilterItemLink ../../parsedQuery 'assigned' 'false'}}">{{t 'unassigned'}}</a>
+ {{else}}
+ <a href="{{issueFilterItemLink ../../parsedQuery 'assignees' val}}">{{default label val}}</a>
+ {{/eq}}
+ </td>
+ <td class="text-right nowrap">
+ {{#notNull ../periodDate}}+{{/notNull}}{{numberShort count}}
+ </td>
+ <td class="barchart">
+ <div class="barchart" style="width: 100%;">
+ <div style="width: {{percent count ../total}};"></div>
+ </div>
+ </td>
+ </tr>
+ {{/each}}
+</table>
+
+{{#if maxResultsReached}}
+ {{> '_widget-issue-filter-limit'}}
+{{/if}}
diff --git a/server/sonar-web/src/main/js/widgets/issue-filter/templates/widget-issue-filter-resolutions.hbs b/server/sonar-web/src/main/js/widgets/issue-filter/templates/widget-issue-filter-resolutions.hbs
new file mode 100644
index 00000000000..50827ba41bb
--- /dev/null
+++ b/server/sonar-web/src/main/js/widgets/issue-filter/templates/widget-issue-filter-resolutions.hbs
@@ -0,0 +1,26 @@
+<table class="data zebra">
+ {{> '_widget-issue-filter-total'}}
+ {{#each items}}
+ <tr>
+ <td>
+ {{#eq val ''}}
+ <a href="{{issueFilterItemLink ../../parsedQuery 'resolved' 'false'}}">{{t 'unresolved'}}</a>
+ {{else}}
+ <a href="{{issueFilterItemLink ../../parsedQuery 'resolutions' val}}">{{t 'issue.resolution' val}}</a>
+ {{/eq}}
+ </td>
+ <td class="text-right nowrap">
+ {{#notNull ../periodDate}}+{{/notNull}}{{numberShort count}}
+ </td>
+ <td class="barchart">
+ <div class="barchart" style="width: 100%;">
+ <div style="width: {{percent count ../total}};"></div>
+ </div>
+ </td>
+ </tr>
+ {{/each}}
+</table>
+
+{{#if maxResultsReached}}
+ {{> '_widget-issue-filter-limit'}}
+{{/if}}
diff --git a/server/sonar-web/src/main/js/widgets/issue-filter/templates/widget-issue-filter-severities.hbs b/server/sonar-web/src/main/js/widgets/issue-filter/templates/widget-issue-filter-severities.hbs
new file mode 100644
index 00000000000..3ca50c03da5
--- /dev/null
+++ b/server/sonar-web/src/main/js/widgets/issue-filter/templates/widget-issue-filter-severities.hbs
@@ -0,0 +1,23 @@
+<table class="data zebra">
+ <tr>
+ <td>
+ <a href="{{issueFilterTotalLink parsedQuery}}"><strong>{{t 'total'}}</strong></a>
+ </td>
+ <td class="text-right"><strong>{{#notNull periodDate}}+{{/notNull}}{{numberShort total}}</strong></td>
+ </tr>
+ {{#each items}}
+ <tr>
+ <td>
+ {{severityIcon val}}
+ <a href="{{issueFilterItemLink ../parsedQuery ../property val}}">{{t 'severity' val}}</a>
+ </td>
+ <td class="text-right nowrap">
+ {{#notNull ../periodDate}}+{{/notNull}}{{numberShort count}}
+ </td>
+ </tr>
+ {{/each}}
+</table>
+
+{{#if maxResultsReached}}
+ {{> '_widget-issue-filter-limit'}}
+{{/if}}
diff --git a/server/sonar-web/src/main/js/widgets/issue-filter/templates/widget-issue-filter-statuses.hbs b/server/sonar-web/src/main/js/widgets/issue-filter/templates/widget-issue-filter-statuses.hbs
new file mode 100644
index 00000000000..70d5a57c765
--- /dev/null
+++ b/server/sonar-web/src/main/js/widgets/issue-filter/templates/widget-issue-filter-statuses.hbs
@@ -0,0 +1,23 @@
+<table class="data zebra">
+ {{> '_widget-issue-filter-total'}}
+ {{#each items}}
+ <tr>
+ <td>
+ {{statusIcon val}}
+ <a href="{{issueFilterItemLink ../parsedQuery ../property val}}">{{t 'issue.status' val}}</a>
+ </td>
+ <td class="text-right nowrap">
+ {{#notNull ../periodDate}}+{{/notNull}}{{numberShort count}}
+ </td>
+ <td class="barchart">
+ <div class="barchart" style="width: 100%;">
+ <div style="width: {{percent count ../total}};"></div>
+ </div>
+ </td>
+ </tr>
+ {{/each}}
+</table>
+
+{{#if maxResultsReached}}
+ {{> '_widget-issue-filter-limit'}}
+{{/if}}
diff --git a/server/sonar-web/src/main/js/widgets/issue-filter/templates/widget-issue-filter.hbs b/server/sonar-web/src/main/js/widgets/issue-filter/templates/widget-issue-filter.hbs
new file mode 100644
index 00000000000..dc78bba0232
--- /dev/null
+++ b/server/sonar-web/src/main/js/widgets/issue-filter/templates/widget-issue-filter.hbs
@@ -0,0 +1,22 @@
+<table class="data zebra">
+ {{> '_widget-issue-filter-total'}}
+ {{#each items}}
+ <tr>
+ <td>
+ <a href="{{searchLink}}">{{default label val}}</a>
+ </td>
+ <td class="text-right nowrap">
+ {{#notNull ../periodDate}}+{{/notNull}}{{numberShort count}}
+ </td>
+ <td class="barchart">
+ <div class="barchart" style="width: 100%;">
+ <div style="width: {{percent count ../total}};"></div>
+ </div>
+ </td>
+ </tr>
+ {{/each}}
+</table>
+
+{{#if maxResultsReached}}
+ {{> '_widget-issue-filter-limit'}}
+{{/if}}
diff --git a/server/sonar-web/src/main/js/widgets/issue-filter.js b/server/sonar-web/src/main/js/widgets/issue-filter/widget.js
index cea0f151b50..2fb96c7d2e7 100644
--- a/server/sonar-web/src/main/js/widgets/issue-filter.js
+++ b/server/sonar-web/src/main/js/widgets/issue-filter/widget.js
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-define(['templates/widgets'], function () {
+define(['./templates'], function () {
var $ = jQuery,
FACET_LIMIT = 15,
diff --git a/server/sonar-web/src/main/js/widgets/pie-chart.js b/server/sonar-web/src/main/js/widgets/pie-chart.js
deleted file mode 100644
index a88f0941c55..00000000000
--- a/server/sonar-web/src/main/js/widgets/pie-chart.js
+++ /dev/null
@@ -1,417 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-/*global d3:false, baseUrl:false */
-/*jshint eqnull:true */
-
-window.SonarWidgets = window.SonarWidgets == null ? {} : window.SonarWidgets;
-
-(function () {
-
- window.SonarWidgets.PieChart = function () {
- // Set default values
- this._components = [];
- this._metrics = [];
- this._metricsPriority = [];
- 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._legendMargin = window.SonarWidgets.PieChart.defaults.legendMargin;
- this._detailsWidth = window.SonarWidgets.PieChart.defaults.detailsWidth;
- this._options = {};
-
- this._lineHeight = 20;
-
-
- // Export global variables
- this.metrics = function (_) {
- return param.call(this, '_metrics', _);
- };
-
- this.metricsPriority = function (_) {
- return param.call(this, '_metricsPriority', _);
- };
-
- this.components = function (_) {
- return param.call(this, '_components', _);
- };
-
- 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', _);
- };
-
- this.legendMargin = function (_) {
- return param.call(this, '_legendMargin', _);
- };
-
- this.detailsWidth = function (_) {
- return param.call(this, '_detailsWidth', _);
- };
-
- this.options = function (_) {
- return param.call(this, '_options', _);
- };
- };
-
- window.SonarWidgets.PieChart.prototype.render = function (container) {
- var widget = this,
- containerS = container;
-
- container = d3.select(container);
-
-
- var validData = this.components().reduce(function(p, c) {
- return p && !!c.measures[widget.metricsPriority()[0]];
- }, true);
-
- if (!validData) {
- container.text(this.options().noMainMetric);
- return;
- }
-
-
- 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')
- .classed('plot', true);
-
- this.gWrap
- .attr('transform', trans(this.margin().left, this.margin().top));
-
-
- // Configure metrics
- this.mainMetric = this.metricsPriority()[0];
- this.getMainMetric = function(d) {
- return d.measures[widget.mainMetric].val;
- };
-
-
- // Configure scales
- this.color = d3.scale.category10();
-
-
- // Configure arc
- this.arc = d3.svg.arc()
- .innerRadius(0);
-
-
- // Configure pie
- this.pie = d3.layout.pie()
- .sort(null)
- .value(function(d) { return widget.getMainMetric(d); });
-
-
- // Configure legend
- this.legendWrap = this.gWrap.append('g');
-
-
- // Configure details
- this._metricsCount = Object.keys(this.metrics()).length + 1;
- this._detailsHeight = this._lineHeight * this._metricsCount;
-
- this.detailsWrap = this.gWrap.append('g')
- .attr('width', this.legendWidth())
- .style('display', 'none');
-
- this.detailsColorIndicator = this.detailsWrap.append('rect')
- .classed('details-color-indicator', true)
- .attr('transform', trans(-1, 0))
- .attr('x', 0)
- .attr('y', 0)
- .attr('width', 3)
- .attr('height', this._detailsHeight)
- .style('opacity', 0);
-
- this.donutLabel = this.plotWrap.append('text')
- .style('text-anchor', 'middle')
- .style('opacity', 0);
-
- this.donutLabel2 = this.plotWrap.append('text')
- .style('text-anchor', 'middle')
- .text(this.metrics()[this.mainMetric].name);
-
-
- // Update widget
- this.update(containerS);
-
- return this;
- };
-
-
- window.SonarWidgets.PieChart.prototype.updateLegend = function () {
- var widget = this;
- this.legendWrap
- .attr('transform', trans(
- this.legendMargin() + 2 * this.radius,
- (this.availableHeight - this._legendSize * this._lineHeight) / 2
- ));
-
- this.legends = this.legendWrap.selectAll('.legend')
- .data(this.components().slice(0, this._legendSize));
-
- this.legendsEnter = this.legends.enter()
- .append('g')
- .classed('legend pie-legend', true)
- .attr('transform', function(d, i) { return trans(0, 10 + i * widget._lineHeight); });
-
- this.legendsEnter.append('circle')
- .attr('class', 'legend-bullet')
- .attr('r', 4)
- .style('fill', function(d, i) { return widget.color(i); });
-
- this.legendsEnter.append('text')
- .attr('class', 'legend-text')
- .attr('dy', '0.1em')
- .attr('transform', trans(10, 3));
-
- this.legends.selectAll('text')
- .text(function(d) {
- return d.name.length > widget._legendSymbols ? d.name.substr(0, widget._legendSymbols) + '...' : d.name;
- });
- };
-
-
- window.SonarWidgets.PieChart.prototype.updateDetails = function () {
- var widget = this;
- this.detailsWrap
- .attr('width', this.legendWidth())
- .attr('transform', trans(
- this.legendMargin() + 2 * this.radius, this.radius - this._detailsHeight / 2
- ));
-
- this.donutLabel
- .transition()
- .style('font-size', (this.radius / 6) + 'px');
-
- var fz = Math.min(
- 12,
- this.radius / 10,
- 1.5 * this.radius / this.metrics()[this.mainMetric].name.length
- );
- this.donutLabel2
- .attr('transform', trans(0, widget.radius / 6))
- .style('font-size', fz + 'px');
- };
-
-
- window.SonarWidgets.PieChart.prototype.configureEvents = function () {
- var widget = this;
- var 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();
- },
- enterHandler = function(sector, d, i, showDetails) {
- if (showDetails) {
- var metrics = widget.metricsPriority().map(function(m) {
- return {
- name: widget.metrics()[m].name,
- value: (!!d.measures[m] ? d.measures[m].fval : '–')
- };
- });
- metrics.unshift({
- name: (d.name.length > widget._legendSymbols ? d.name.substr(0, widget._legendSymbols) + '...' : d.name)
- });
- updateMetrics(metrics);
-
- widget.legendWrap
- .style('opacity', 0);
-
- widget.detailsColorIndicator
- .style('opacity', 1)
- .style('fill', widget.color(i));
-
- widget.detailsWrap
- .style('display', 'block');
- }
- widget.donutLabel
- .style('opacity', 1)
- .text(d.measures[widget.mainMetric].fval);
- widget.donutLabel
- .style('opacity', 1);
- widget.plotWrap
- .classed('hover', true);
- sector.
- classed('hover', true);
- },
-
- leaveHandler = function(sector) {
- widget.legendWrap
- .style('opacity', 1);
- widget.detailsColorIndicator
- .style('opacity', 0);
- if (widget.detailsMetrics) {
- widget.detailsMetrics
- .style('opacity', 0);
- }
- widget.donutLabel
- .style('opacity', 0)
- .text('');
- widget.plotWrap
- .classed('hover', false);
- sector.
- classed('hover', false);
- widget.detailsWrap
- .style('display', 'none');
- },
-
- clickHandler = function(d) {
- window.location = widget.options().baseUrl + '?id=' + encodeURIComponent(d.key);
- };
-
- this.sectors
- .on('mouseenter', function(d, i) {
- return enterHandler(d3.select(this), d.data, i, true);
- })
- .on('mouseleave', function(d, i) {
- return leaveHandler(d3.select(this), d.data, i, true);
- })
- .on('click', function(d) {
- return clickHandler(d.data);
- });
-
- this.legends
- .on('mouseenter', function(d, i) {
- return enterHandler(d3.select(widget.sectors[0][i]), d, i, false);
- })
- .on('mouseleave', function(d, i) {
- return leaveHandler(d3.select(widget.sectors[0][i]), d, i, false);
- })
- .on('click', function(d) {
- return clickHandler(d);
- });
- };
-
-
- 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.legendMargin();
- this.availableHeight = this.height() - this.margin().top - this.margin().bottom;
- this.radius = Math.min(this.availableWidth, this.availableHeight) / 2;
- this._legendSize = Math.floor(this.availableHeight / this._lineHeight);
- this._legendSymbols = Math.floor((this.width() - this.margin().left - this.margin().right -
- this.legendMargin() - 2 * this.radius) / 6.2);
-
-
- // Update plot
- this.plotWrap
- .attr('transform', trans(this.radius, this.radius));
-
-
- // Update arc
- this.arc
- .innerRadius(this.radius / 2)
- .outerRadius(this.radius);
-
-
- // 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();
-
-
- this.updateLegend();
- this.updateDetails();
- this.configureEvents();
- };
-
-
-
- window.SonarWidgets.PieChart.defaults = {
- width: 350,
- height: 300,
- margin: { top: 10, right: 10, bottom: 10, left: 10 },
- legendWidth: 160,
- legendMargin: 30
- };
-
-
-
- // 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 + ')';
- }
-
-})();
diff --git a/server/sonar-web/src/main/js/widgets/stack-area.js b/server/sonar-web/src/main/js/widgets/stack-area.js
deleted file mode 100644
index 993828be5bf..00000000000
--- a/server/sonar-web/src/main/js/widgets/stack-area.js
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-window.SonarWidgets = window.SonarWidgets == null ? {} : window.SonarWidgets;
-
-(function () {
-
- window.SonarWidgets.StackArea = function (container) {
-
- // Ensure container is html id
- if (container.indexOf('#') !== 0) {
- container = '#' + container;
- }
-
- this.container = d3.select(container);
-
-
- // Set default values
- this._data = [];
- this._metrics = [];
- this._snapshots = [];
- this._colors = [];
- this._width = window.SonarWidgets.StackArea.defaults.width;
- this._height = window.SonarWidgets.StackArea.defaults.height;
- this._margin = window.SonarWidgets.StackArea.defaults.margin;
-
- // Export global variables
- this.data = function (_) {
- return param.call(this, '_data', _);
- };
-
- this.metrics = function (_) {
- return param.call(this, '_metrics', _);
- };
-
- this.snapshots = function (_) {
- return param.call(this, '_snapshots', _);
- };
-
- this.colors = function (_) {
- return param.call(this, '_colors', _);
- };
-
- this.width = function (_) {
- return param.call(this, '_width', _);
- };
-
- this.height = function (_) {
- return param.call(this, '_height', _);
- };
-
- this.margin = function (_) {
- return param.call(this, '_margin', _);
- };
-
- };
-
-
- window.SonarWidgets.StackArea.prototype.initScales = function() {
- var widget = this,
- colorsLength = widget.colors().length;
- var timeDomain = this.data()
- .map(function(_) {
- return d3.extent(_, function(d) {
- return d.x;
- });
- })
- .reduce(function(p, c) {
- return p.concat(c);
- }, []);
-
- this.time = d3.time.scale().domain(d3.extent(timeDomain));
-
- this.y = d3.scale.linear()
- .domain([0, d3.max(this.stackDataTop, function(d) {
- return d.y0 + d.y;
- })])
- .nice();
-
- this.color = function(i) {
- return widget.colors()[i % colorsLength][0];
- };
- };
-
-
- window.SonarWidgets.StackArea.prototype.initAxis = function() {
- this.timeAxis = d3.svg.axis()
- .scale(this.time)
- .orient('bottom')
- .ticks(5);
- };
-
-
- window.SonarWidgets.StackArea.prototype.initArea = function() {
- var widget = this;
- this.area = d3.svg.area()
- .x(function(d) { return widget.time(d.x); })
- .y0(function(d) { return widget.y(d.y0); })
- .y1(function(d) { return widget.y(d.y0 + d.y); });
-
- this.areaLine = d3.svg.line()
- .x(function(d) { return widget.time(d.x); })
- .y(function(d) { return widget.y(d.y0 + d.y); });
- };
-
-
- window.SonarWidgets.StackArea.prototype.initInfo = function() {
- var widget = this;
- this.infoWrap
- .attr('class', 'info')
- .attr('transform', trans(0, -60));
-
- this.infoDate
- .attr('class', 'info-text info-text-bold')
- .attr('transform', trans(0, 0));
-
- this.infoTotal
- .attr('class', 'info-text info-text-small')
- .attr('transform', trans(0, 18));
-
- this.infoSnapshot
- .attr('class', 'info-text info-text-small')
- .attr('transform', trans(0, 54));
-
- this.infoMetrics = [];
- var prevX = 120;
- this.metrics().forEach(function(d, i) {
- var infoMetric = widget.infoWrap.append('g');
-
- var infoMetricText = infoMetric.append('text')
- .attr('class', 'info-text-small')
- .attr('transform', trans(10, 0))
- .text(widget.metrics()[i]);
-
- infoMetric.append('circle')
- .attr('transform', trans(0, -4))
- .attr('r', 4)
- .style('fill', function() { return widget.color(i); });
-
- // Align metric labels
- infoMetric
- .attr('transform', function() {
- return trans(prevX, -1 + (i % 3) * 18);
- });
-
- widget.infoMetrics.push(infoMetric);
-
- if (i % 3 === 2) {
- prevX += (infoMetricText.node().getComputedTextLength() + 70);
- }
- });
- };
-
-
- window.SonarWidgets.StackArea.prototype.initEvents = function() {
- var widget = this;
- this.events = widget.snapshots()
- .filter(function(d) { return d.e.length > 0; });
-
- this.gevents = this.gWrap.append('g')
- .attr('class', 'axis events')
- .selectAll('.event-tick')
- .data(this.events);
-
- this.gevents.enter().append('line')
- .attr('class', 'event-tick')
- .attr('y2', -8);
-
-
- this.selectSnapshot = function(cl) {
- var dataX = widget.data()[0][cl].x,
- sx = widget.time(dataX),
- snapshotIndex = null,
- eventIndex = null;
-
- // Update scanner position
- widget.scanner
- .attr('x1', sx)
- .attr('x2', sx);
-
-
- // Update metric labels
- var metricsLines = widget.data().map(function(d, i) {
- var value = d[cl].fy || d[cl].y;
- return widget.metrics()[i] + ': ' + value;
- });
-
- metricsLines.forEach(function(d, i) {
- widget.infoMetrics[i].select('text').text(d);
- });
-
-
- // Update snapshot info
- this.snapshots().forEach(function(d, i) {
- if (d.d - dataX === 0) {
- snapshotIndex = i;
- }
- });
-
- if (snapshotIndex != null) {
- widget.infoSnapshot
- .text(this.snapshots()[snapshotIndex].e.join(', '));
- }
-
-
- // Update info
- widget.infoDate
- .text(moment(widget.data()[0][cl].x).format('LL'));
-
- var snapshotValue = this.snapshots()[snapshotIndex].fy,
- totalValue = snapshotValue || (widget.stackDataTop[cl].y0 + widget.stackDataTop[cl].y);
- widget.infoTotal
- .text('Total: ' + totalValue);
-
-
- // Update event
- this.events.forEach(function(d, i) {
- if (d.d - dataX === 0) {
- eventIndex = i;
- }
- });
-
- widget.gevents.attr('y2', -8);
- d3.select(widget.gevents[0][eventIndex]).attr('y2', -12);
- };
-
-
- // Set event listeners
- this.svg.on('mousemove', function() {
- var mx = d3.mouse(widget.plotWrap.node())[0],
- cl = closest(widget.data()[0], mx, function(d) { return widget.time(d.x); });
- widget.selectSnapshot(cl);
- });
- };
-
-
- window.SonarWidgets.StackArea.prototype.render = function () {
- this.svg = this.container.append('svg')
- .attr('class', 'sonar-d3');
-
- this.gWrap = this.svg.append('g');
-
- this.gtimeAxis = this.gWrap.append('g')
- .attr('class', 'axis x');
-
- this.plotWrap = this.gWrap.append('g')
- .attr('class', 'plot');
-
- this.scanner = this.plotWrap.append('line');
-
- this.infoWrap = this.gWrap.append('g');
- this.infoDate = this.infoWrap.append('text');
- this.infoSnapshot = this.infoWrap.append('text');
- this.infoTotal = this.infoWrap.append('text');
-
- this.gWrap
- .attr('transform', trans(this.margin().left, this.margin().top));
-
- // Configure stack
- this.stack = d3.layout.stack();
- this.stackData = this.stack(this.data());
- this.stackDataTop = this.stackData[this.stackData.length - 1];
-
- this.initScales();
- this.initAxis();
- this.initArea();
-
- // Configure scanner
- this.scanner
- .attr('class', 'scanner')
- .attr('y1', 0);
-
- this.initInfo();
- this.initEvents();
- this.update();
-
- return this;
- };
-
-
- window.SonarWidgets.StackArea.prototype.update = function() {
- var widget = this,
- width = this.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.availableHeight = this.height() - this.margin().top - this.margin().bottom;
-
-
- // Update scales
- this.time.range([0, this.availableWidth]);
- this.y.range([widget.availableHeight, 0]);
-
-
- // Update the axis
- this.gtimeAxis.attr('transform', trans(0, this.availableHeight + this.margin().bottom - 30));
- this.gtimeAxis.transition().call(this.timeAxis);
-
-
- // Update area
- this.garea = this.plotWrap.selectAll('.area')
- .data(this.stackData)
- .enter()
- .insert('path', ':first-child')
- .attr('class', 'area')
- .attr('d', function(d) { return widget.area(d); })
- .style('fill', function(d, i) { return widget.color(i); });
-
- this.gareaLine = this.plotWrap.selectAll('.area-line')
- .data(this.stackData)
- .enter()
- .insert('path')
- .attr('class', 'area-line')
- .attr('d', function(d) { return widget.areaLine(d); })
- .style('fill', 'none')
- .style('stroke', '#808080');
-
-
- // Update scanner
- this.scanner.attr('y2', this.availableHeight + 10);
-
-
- // Update events
- this.gevents
- .transition()
- .attr('transform', function(d) {
- return trans(widget.time(d.d), widget.availableHeight + 10);
- });
-
-
- // Select latest values if this it the first update
- if (!this.firstUpdate) {
- this.selectSnapshot(widget.data()[0].length - 1);
-
- this.firstUpdate = true;
- }
-
- };
-
-
-
- window.SonarWidgets.StackArea.defaults = {
- width: 350,
- height: 150,
- margin: { top: 80, right: 10, bottom: 40, left: 40 }
- };
-
-
-
- // 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 + ')';
- }
-
- // Helper for find the closest number in array
- function closest(array, number, getter) {
- var cl = null;
- array.forEach(function(value, i) {
- if (cl == null ||
- Math.abs(getter(value) - number) < Math.abs(getter(array[cl]) - number)) {
- cl = i;
- }
- });
- return cl;
- }
-
-})();
diff --git a/server/sonar-web/src/main/js/widgets/timeline.js b/server/sonar-web/src/main/js/widgets/timeline.js
deleted file mode 100644
index 5b871e5994e..00000000000
--- a/server/sonar-web/src/main/js/widgets/timeline.js
+++ /dev/null
@@ -1,417 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-/*global d3:false*/
-
-window.SonarWidgets = window.SonarWidgets == null ? {} : window.SonarWidgets;
-
-(function () {
-
- window.SonarWidgets.Timeline = function (container) {
-
- // Ensure container is html id
- if (container.indexOf('#') !== 0) {
- container = '#' + container;
- }
-
- this.container = d3.select(container);
-
- // Set default values
- this._data = [];
- this._metrics = [];
- this._snapshots = [];
- this._events = [];
- this._width = window.SonarWidgets.Timeline.defaults.width;
- this._height = window.SonarWidgets.Timeline.defaults.height;
- this._margin = window.SonarWidgets.Timeline.defaults.margin;
-
- // Export global variables
- this.data = function (_) {
- return param.call(this, '_data', _);
- };
-
- this.metrics = function (_) {
- return param.call(this, '_metrics', _);
- };
-
- this.snapshots = function (_) {
- return param.call(this, '_snapshots', _);
- };
-
- this.events = function (_) {
- return param.call(this, '_events', _);
- };
-
- this.width = function (_) {
- return param.call(this, '_width', _);
- };
-
- this.height = function (_) {
- return param.call(this, '_height', _);
- };
-
- this.margin = function (_) {
- return param.call(this, '_margin', _);
- };
-
- };
-
-
- window.SonarWidgets.Timeline.prototype.initScalesAndAxis = function () {
- // Configure scales
- var timeDomain = this.data()
- .map(function(_) {
- return d3.extent(_, function(d) {
- return d.x;
- });
- })
- .reduce(function(p, c) {
- return p.concat(c);
- }, []);
-
- this.time = d3.time.scale().domain(d3.extent(timeDomain));
-
- this.y = this.data().map(function(_) {
- return d3.scale.linear()
- .domain(d3.extent(_, function(d) { return d.y; }));
- });
-
- this.color = d3.scale.category10();
-
- // Configure the axis
- this.timeAxis = d3.svg.axis()
- .scale(this.time)
- .orient('bottom')
- .ticks(5);
- };
-
-
- window.SonarWidgets.Timeline.prototype.initEvents = function () {
- var widget = this;
- this.events(this.events().filter(function (event) {
- return event.d >= widget.time.domain()[0];
- }));
-
- this.gevents = this.gWrap.append('g')
- .attr('class', 'axis events')
- .selectAll('.event-tick')
- .data(this.events());
-
- this.gevents.enter().append('line')
- .attr('class', 'event-tick')
- .attr('y2', -8);
-
- this.gevents.exit().remove();
-
-
- this.selectSnapshot = function(cl) {
- var sx = widget.time(widget.data()[0][cl].x);
-
- widget.markers.forEach(function(marker) {
- marker.style('opacity', 0);
- d3.select(marker[0][cl]).style('opacity', 1);
- });
-
- widget.scanner
- .attr('x1', sx)
- .attr('x2', sx);
-
- widget.infoDate
- .text(moment(widget.data()[0][cl].x).format('LL'));
-
- var metricsLines = widget.data().map(function(d, i) {
- return widget.metrics()[i] + ': ' + d[cl].yl;
- });
-
- metricsLines.forEach(function(d, i) {
- widget.infoMetrics[i].select('text').text(d);
- });
-
- widget.gevents.attr('y2', -8);
- widget.infoEvent.text('');
- widget.events().forEach(function(d, i) {
- if (d.d - widget.data()[0][cl].x === 0) {
- d3.select(widget.gevents[0][i]).attr('y2', -12);
-
- widget.infoEvent
- .text(widget.events()[i].l
- .map(function(e) { return e.n; })
- .join(', '));
- }
- });
- };
-
-
- // Set event listeners
- this.svg.on('mousemove', function() {
- var mx = d3.mouse(widget.plotWrap.node())[0],
- cl = closest(widget.data()[0], mx, function(d) { return widget.time(d.x); });
- widget.selectSnapshot(cl);
- });
- };
-
-
- window.SonarWidgets.Timeline.prototype.render = function () {
- var widget = this;
-
- this.svg = this.container.append('svg')
- .attr('class', 'sonar-d3');
-
- this.gWrap = this.svg.append('g');
-
- this.gtimeAxis = this.gWrap.append('g')
- .attr('class', 'axis x');
-
- this.plotWrap = this.gWrap.append('g')
- .attr('class', 'plot');
-
- this.scanner = this.plotWrap.append('line');
-
- this.infoWrap = this.gWrap.append('g')
- .attr('class', 'info');
-
- this.infoDate = this.infoWrap.append('text')
- .attr('class', 'info-text info-text-bold');
-
- this.infoEvent = this.infoWrap.append('text')
- .attr('class', 'info-text info-text-small');
-
- this.gWrap
- .attr('transform', trans(this.margin().left, this.margin().top));
-
- this.initScalesAndAxis();
- this.showLimitHistoryMessage();
-
- // Configure lines and points
- this.lines = [];
- this.glines = [];
- this.markers = [];
- this.data().forEach(function(_, i) {
- var line = d3.svg.line()
- .x(function(d) { return widget.time(d.x); })
- .y(function(d) { return widget.y[i](d.y); })
- .interpolate('linear');
-
- var gline = widget.plotWrap.append('path')
- .attr('class', 'line')
- .style('stroke', function() { return widget.color(i); });
-
- widget.lines.push(line);
- widget.glines.push(gline);
-
- var marker = widget.plotWrap.selectAll('.marker').data(_);
- marker.enter().append('circle')
- .attr('class', 'line-marker')
- .attr('r', 3)
- .style('stroke', function() { return widget.color(i); });
- marker.exit().remove();
-
- widget.markers.push(marker);
- });
-
-
- // Configure scanner
- this.scanner
- .attr('class', 'scanner')
- .attr('y1', 0);
-
-
- // Configure info
- this.infoWrap
- .attr('transform', trans(0, -30));
-
- this.infoDate
- .attr('transform', trans(0, 0));
-
- this.infoMetrics = [];
- this.metrics().forEach(function(d, i) {
- var infoMetric = widget.infoWrap.append('g')
- .attr('class', 'metric-legend')
- .attr('transform', function() { return trans(110 + i * 150, -1); });
-
- infoMetric.append('text')
- .attr('class', 'info-text-small')
- .attr('transform', trans(10, 0));
-
- infoMetric.append('circle')
- .attr('class', 'metric-legend-line')
- .attr('transform', trans(0, -4))
- .attr('r', 4)
- .style('fill', function() { return widget.color(i); });
-
- widget.infoMetrics.push(infoMetric);
- });
-
- this.initEvents();
- this.update();
-
- return this;
- };
-
-
- window.SonarWidgets.Timeline.prototype.showLimitHistoryMessage = function () {
- var minEvent = d3.min(this.events(), function (d) {
- return d.d;
- }),
- minData = this.time.domain()[0];
- if (minEvent < minData) {
- var maxResultsReachedLabel = this.container.append('div').text(this.limitedHistoricalData);
- maxResultsReachedLabel.classed('max-results-reached-message', true);
- }
- };
-
-
- window.SonarWidgets.Timeline.prototype.update = function() {
- var widget = this,
- width = this.container.property('offsetWidth');
-
- this.width(width > 100 ? width : 100);
-
-
- // Update svg canvas
- this.svg
- .attr('width', this.width())
- .attr('height', this.height());
-
-
- // Update available width
- this.availableWidth = this.width() - this.margin().left - this.margin().right;
-
-
- // Update metric lines
- var metricY = -1;
- this.infoMetrics.forEach(function(metric, i) {
- var x = 120 + i * 170,
- x2 = x + 170;
-
- if (x2 > widget.availableWidth) {
- metricY += 18;
- x = 120;
- }
-
- metric
- .transition()
- .attr('transform', function() { return trans(x, metricY); });
- });
-
- if (metricY > -1) {
- metricY += 17;
- }
-
- // Update available width
- this.availableHeight = this.height() - this.margin().top - this.margin().bottom - metricY;
-
-
- // Update scales
- this.time
- .range([0, this.availableWidth]);
-
- this.y.forEach(function(scale) {
- scale.range([widget.availableHeight, 0]);
- });
-
-
- // Update plot
- this.plotWrap
- .transition()
- .attr('transform', trans(0, metricY));
-
-
- // Update the axis
- this.gtimeAxis.attr('transform', trans(0, this.availableHeight + this.margin().bottom - 30 + metricY));
-
- this.gtimeAxis.transition().call(this.timeAxis);
-
-
- // Update lines and points
- this.data().forEach(function(_, i) {
- widget.glines[i]
- .transition()
- .attr('d', widget.lines[i](_));
-
- widget.markers[i]
- .data(_)
- .transition()
- .attr('transform', function(d) { return trans(widget.time(d.x), widget.y[i](d.y)); });
- });
-
-
- // Update scanner
- this.scanner
- .attr('y2', this.availableHeight + 10);
-
-
- // Update events
- this.infoEvent
- .attr('transform', trans(0, metricY > -1 ? metricY : 18));
-
- this.gevents
- .transition()
- .attr('transform', function(d) { return trans(widget.time(d.d), widget.availableHeight + 10 + metricY); });
-
-
- // Select latest values if this it the first update
- if (!this.firstUpdate) {
- this.selectSnapshot(widget.data()[0].length - 1);
-
- this.firstUpdate = true;
- }
-
- };
-
-
-
- window.SonarWidgets.Timeline.defaults = {
- width: 350,
- height: 150,
- margin: { top: 50, right: 10, bottom: 40, left: 10 }
- };
-
-
-
- // 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 + ')';
- }
-
- // Helper for find the closest number in array
- function closest(array, number, getter) {
- var cl = null;
- array.forEach(function(value, i) {
- if (cl == null ||
- Math.abs(getter(value) - number) < Math.abs(getter(array[cl]) - number)) {
- cl = i;
- }
- });
- return cl;
- }
-
-})();
diff --git a/server/sonar-web/src/main/js/widgets/widget.js b/server/sonar-web/src/main/js/widgets/widget.js
deleted file mode 100644
index cd30319f885..00000000000
--- a/server/sonar-web/src/main/js/widgets/widget.js
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-/*global d3:false, SonarWidgets:false */
-/*jshint eqnull:true */
-
-window.SonarWidgets = window.SonarWidgets == null ? {} : window.SonarWidgets;
-
-(function () {
-
- window.SonarWidgets.Widget = function () {
- // Set default values
- this._type = null;
- this._source = null;
- this._metricsPriority = null;
- this._height = null;
- this._options = {};
-
-
- // Export global variables
- this.type = function (_) {
- return param.call(this, '_type', _);
- };
-
- this.source = function (_) {
- return param.call(this, '_source', _);
- };
-
- this.metricsPriority = function (_) {
- return param.call(this, '_metricsPriority', _);
- };
-
- this.height = function (_) {
- return param.call(this, '_height', _);
- };
-
- this.options = function (_) {
- return param.call(this, '_options', _);
- };
- };
-
-
- window.SonarWidgets.Widget.prototype.render = function(container) {
- var that = this;
-
- this.showSpinner(container);
- d3.json(this.source(), function(error, response) {
- if (response && !error) {
- that.hideSpinner();
- if (typeof response.components === 'undefined' || response.components.length > 0) {
- that.widget = new SonarWidgets[that.type()]();
- that.widget.metricsPriority(that.metricsPriority());
- that.widget.options(that.options());
- that.widget.metrics(response.metrics);
- that.widget.components(response.components);
- if(typeof that.widget.parseSource === 'function') {
- that.widget.parseSource(response);
- }
- if (typeof that.widget.maxResultsReached === 'function') {
- that.widget.maxResultsReached(response.paging != null && response.paging.pages > 1);
- }
- if (that.height()) {
- that.widget.height(that.height());
- }
- that.widget.render(container);
- } else {
- d3.select(container).html(that.options().noData);
- }
- }
- });
- };
-
-
- window.SonarWidgets.Widget.prototype.showSpinner = function(container) {
- this.spinner = d3.select(container).append('i').classed('spinner', true);
- };
-
-
- window.SonarWidgets.Widget.prototype.hideSpinner = function() {
- if (this.spinner) {
- this.spinner.remove();
- }
- };
-
-
- window.SonarWidgets.Widget.prototype.update = function(container) {
- return this.widget && this.widget.update(container);
- };
-
-
-
- // Some helper functions
-
- // Gets or sets parameter
- function param(name, value) {
- if (value == null) {
- return this[name];
- } else {
- this[name] = value;
- return this;
- }
- }
-
-})();