aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Gageot <david@gageot.net>2012-05-09 10:31:33 +0200
committerDavid Gageot <david@gageot.net>2012-05-09 11:22:55 +0200
commitc90a83404de632683567072a5dd75a70d1a15594 (patch)
treec7e07a2fe11727f7b27c9dadc9c1b8b207b6f6c0
parent882dab818134eca6353509d7ab92f80bcabbac5d (diff)
downloadsonarqube-c90a83404de632683567072a5dd75a70d1a15594.tar.gz
sonarqube-c90a83404de632683567072a5dd75a70d1a15594.zip
SONAR-1927 Implement a Global Widget that can display Complexity of a given project
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java1
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/TestComplexityWidget.java47
-rw-r--r--plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/test_complexity.html.erb118
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/web/WidgetPropertyType.java3
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/helpers/widget_properties_helper.rb3
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/models/widget_property.rb3
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/dashboard/_configure_widget.html.erb21
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/dashboard/_widget.html.erb20
8 files changed, 215 insertions, 1 deletions
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java
index 2541173c051..e9ac361baa9 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java
@@ -249,6 +249,7 @@ public final class CorePlugin extends SonarPlugin {
extensions.add(CommentsDuplicationsWidget.class);
extensions.add(DescriptionWidget.class);
extensions.add(ComplexityWidget.class);
+ extensions.add(TestComplexityWidget.class);
extensions.add(RulesWidget.class);
extensions.add(SizeWidget.class);
extensions.add(EventsWidget.class);
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/TestComplexityWidget.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/TestComplexityWidget.java
new file mode 100644
index 00000000000..1a5865a9e0d
--- /dev/null
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/TestComplexityWidget.java
@@ -0,0 +1,47 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.plugins.core.widgets;
+
+import org.sonar.api.web.AbstractRubyTemplate;
+import org.sonar.api.web.RubyRailsWidget;
+import org.sonar.api.web.WidgetGlobal;
+import org.sonar.api.web.WidgetProperties;
+import org.sonar.api.web.WidgetProperty;
+import org.sonar.api.web.WidgetPropertyType;
+
+@WidgetGlobal
+@WidgetProperties({
+ @WidgetProperty(key = "project", type = WidgetPropertyType.PROJECT, defaultValue = "1")
+})
+public class TestComplexityWidget extends AbstractRubyTemplate implements RubyRailsWidget {
+
+ public String getId() {
+ return "testComplexity";
+ }
+
+ public String getTitle() {
+ return "TestComplexity";
+ }
+
+ @Override
+ protected String getTemplatePath() {
+ return "/org/sonar/plugins/core/widgets/test_complexity.html.erb";
+ }
+} \ No newline at end of file
diff --git a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/test_complexity.html.erb b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/test_complexity.html.erb
new file mode 100644
index 00000000000..3eb807b0847
--- /dev/null
+++ b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/test_complexity.html.erb
@@ -0,0 +1,118 @@
+<%
+ file_complexity=measure('file_complexity')
+ function_complexity=measure('function_complexity')
+ class_complexity=measure('class_complexity')
+ paragraph_complexity=measure('paragraph_complexity')
+
+ if file_complexity || function_complexity || class_complexity || paragraph_complexity
+complexity=measure('complexity')
+%>
+<table class="width100">
+ <tbody>
+ <tr>
+ <td valign="top" width="50%">
+ <div class="dashbox" >
+ <h3><%= message('widget.complexity.name') -%></h3>
+ <% if function_complexity %>
+ <p>
+ <span class="big"><%= format_measure(function_complexity, :suffix => '', :url => url_for_drilldown(function_complexity)) %></span><%= message('widget.complexity.per_method.suffix') -%>
+ <%= dashboard_configuration.selected_period? ? format_variation(function_complexity) : trend_icon(function_complexity) -%>
+ </p>
+ <% end %>
+ <% if paragraph_complexity %>
+ <p>
+ <span class="big"><%= format_measure(paragraph_complexity, :suffix => '', :url => url_for_drilldown(paragraph_complexity)) %></span><%= message('widget.complexity.per_paragraph.suffix') -%>
+ <%= dashboard_configuration.selected_period? ? format_variation(paragraph_complexity) : trend_icon(paragraph_complexity) -%>
+ </p>
+ <% end %>
+ <% if class_complexity %>
+ <p>
+ <span class="big"><%= format_measure(class_complexity, :suffix => '', :url => url_for_drilldown(class_complexity)) %></span></span><%= message('widget.complexity.per_class.suffix') -%>
+ <%= dashboard_configuration.selected_period? ? format_variation(class_complexity) : trend_icon(class_complexity) -%>
+ </p>
+ <% end %>
+ <% if file_complexity %>
+ <p>
+ <span class="big"><%= format_measure(file_complexity, :suffix => '', :url => url_for_drilldown(file_complexity)) %></span></span><%= message('widget.complexity.per_file.suffix') -%>
+ <%= dashboard_configuration.selected_period? ? format_variation(file_complexity) : trend_icon(file_complexity) -%>
+ </p>
+ <% end %>
+ <% if complexity %>
+ <p>
+ <%= message('widget.complexity.total') -%>: <%= format_measure(complexity, :url => url_for_drilldown(complexity)) -%> <%= dashboard_configuration.selected_period? ? format_variation(complexity) : trend_icon(complexity) -%>
+ </p>
+ <% end %>
+ </div>
+ </td>
+ <td valign="top" width="50%" nowrap>
+<%
+ function_distribution=measure('function_complexity_distribution')
+ paragraph_distribution=measure('paragraph_complexity_distribution')
+ class_distribution=measure('class_complexity_distribution')
+ file_distribution=measure('file_complexity_distribution')
+ distributions=[function_distribution,paragraph_distribution,class_distribution,file_distribution].compact
+ selected_distribution=nil
+ if distributions.size>0
+ selected_distribution=distributions.first
+ end
+ if selected_distribution
+%>
+<div class="dashbox" id="cmp_charts">
+ <script type='text/javascript'>
+ //<![CDATA[
+ function selectComplexity(metric) {
+ $$('#cmp_charts .chart').each(function(chart) {
+ chart.hide();
+ });
+ $('chart_' + metric).show();
+ }
+ </script>
+ <style>
+ #cmp_charts form {
+ font-size: 93%;padding-left: 30px;
+ }
+#cmp_charts form label {
+ padding-right: 5px;
+ }
+ </style>
+ <% distributions.each do |distribution_measure| %>
+ <%= render :partial => 'project/widgets/complexity_chart', :locals => { :metric => distribution_measure.metric.key, :title => distribution_measure.metric.description, :visible => (selected_distribution==distribution_measure) } %>
+ <% end %>
+
+ <form>
+ <%
+ count_dist=0
+ if function_distribution
+ count_dist+=1
+ %>
+<input type="radio" name="cmp_dist" value="function_complexity_distribution" id="cmp_dist_function_complexity_distribution" onClick="selectComplexity('function_complexity_distribution');" <%= 'checked' if function_distribution==selected_distribution -%>></input> <label for="cmp_dist_function_complexity_distribution"><%= message('metric.functions.name') -%></label>
+<%
+end
+if paragraph_distribution
+ count_dist+=1
+%>
+<input type="radio" name="cmp_dist" value="paragraph_complexity_distribution" id="cmp_dist_paragraph_complexity_distribution" onClick="selectComplexity('paragraph_complexity_distribution');" <%= 'checked' if paragraph_distribution==selected_distribution -%>></input> <label for="cmp_dist_paragraph_complexity_distribution"><%= message('metric.paragraphs.name') -%></label><%= '<br/>' if count_dist==2 %>
+<%
+end
+if class_distribution
+ count_dist+=1
+%>
+<input type="radio" name="cmp_dist" value="class_complexity_distribution" id="cmp_dist_class_complexity_distribution" onClick="selectComplexity('class_complexity_distribution');" <%= 'checked' if class_distribution==selected_distribution -%>></input> <label for="cmp_dist_class_complexity_distribution"><%= message('metric.classes.name') -%></label><%= '<br/>' if count_dist==2 %>
+<%
+end
+if file_distribution
+ count_dist+=1
+%>
+<input type="radio" name="cmp_dist" value="file_complexity_distribution" id="cmp_dist_file_complexity_distribution" onClick="selectComplexity('file_complexity_distribution');" <%= 'checked' if file_distribution==selected_distribution -%>></input> <label for="cmp_dist_file_complexity_distribution"><%= message('metric.files.name') -%></label>
+<% end %>
+
+ </form>
+
+</div>
+<% end %>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+<div class="clear"></div>
+<% end %>
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/web/WidgetPropertyType.java b/sonar-plugin-api/src/main/java/org/sonar/api/web/WidgetPropertyType.java
index 7be2caf8b2c..a514287a388 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/web/WidgetPropertyType.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/web/WidgetPropertyType.java
@@ -25,5 +25,6 @@ public enum WidgetPropertyType {
FLOAT,
STRING,
METRIC, // @since 2.10
- FILTER // @since 3.1
+ FILTER, // @since 3.1
+ PROJECT // @since 3.1
}
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/helpers/widget_properties_helper.rb b/sonar-server/src/main/webapp/WEB-INF/app/helpers/widget_properties_helper.rb
index 277209e5b87..bf1e4792e4d 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/helpers/widget_properties_helper.rb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/helpers/widget_properties_helper.rb
@@ -39,6 +39,9 @@ module WidgetPropertiesHelper
elsif definition.type.name()==WidgetProperty::TYPE_FILTER
select_tag definition.key(), ::Filter.all.sort_by(&:id).collect { |f| "<option value='#{f.id}'>#{f.name}</option>" }
+ elsif definition.type.name()==WidgetProperty::TYPE_PROJECT
+ select_tag definition.key(), Project.all(:conditions => {:scope => 'PRJ', :qualifier => 'TRK'}).collect { |f| "<option value='#{f.id}'>#{f.name}</option>" }
+
else
hidden_field_tag definition.key()
end
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/widget_property.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/widget_property.rb
index a26e8e5dfcb..114b1440263 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/models/widget_property.rb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/models/widget_property.rb
@@ -24,6 +24,7 @@ class WidgetProperty < ActiveRecord::Base
TYPE_STRING = 'STRING'
TYPE_METRIC = 'METRIC'
TYPE_FILTER = 'FILTER'
+ TYPE_PROJECT = 'PROJECT'
belongs_to :widget
@@ -84,6 +85,8 @@ class WidgetProperty < ActiveRecord::Base
Metric.by_key(text)
when TYPE_FILTER
text.to_i
+ when TYPE_PROJECT
+ text.to_i
else
text
end
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/dashboard/_configure_widget.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/dashboard/_configure_widget.html.erb
index 61d45160038..812e15e3d99 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/views/dashboard/_configure_widget.html.erb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/views/dashboard/_configure_widget.html.erb
@@ -1,4 +1,17 @@
<%
+ @backup_resource=@resource
+ @backup_project=@project
+ @backup_snapshot=@snapshot
+ @backup_dashboard_configuration=@dashboard_configuration
+
+ if widget.property_value('project')
+ @project = @resource = Project.find(widget.property_value('project'))
+ @snapshot=@resource.last_snapshot
+ @dashboard_configuration=Api::DashboardConfiguration.new(@dashboard, :period_index => params[:period], :snapshot => @snapshot)
+ end
+%>
+
+<%
begin
widget_body=render :inline => widget.java_definition.getTarget().getTemplate(), :locals => {:widget_properties => widget.properties_as_hash, :widget => widget, :dashboard_configuration => @dashboard_configuration}
rescue => error
@@ -51,3 +64,11 @@
<div style="clear: both;"></div>
</div>
+<%
+ @resource=@backup_resource
+ @project=@backup_project
+ @snapshot=@backup_snapshot
+ @dashboard_configuration=@backup_dashboard_configuration
+%>
+
+
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/dashboard/_widget.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/dashboard/_widget.html.erb
index 035b4a87c94..474737e744b 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/views/dashboard/_widget.html.erb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/views/dashboard/_widget.html.erb
@@ -1,3 +1,16 @@
+<%
+ @backup_resource=@resource
+ @backup_project=@project
+ @backup_snapshot=@snapshot
+ @backup_dashboard_configuration=@dashboard_configuration
+
+ if widget.property_value('project')
+ @project = @resource = Project.find(widget.property_value('project'))
+ @snapshot=@resource.last_snapshot
+ @dashboard_configuration=Api::DashboardConfiguration.new(@dashboard, :period_index => params[:period], :snapshot => @snapshot)
+ end
+%>
+
<div class="<%= h widget.key -%>" style="height:100%;">
<% if widget.configured
begin
@@ -29,3 +42,10 @@
<% end %>
<div style="clear: both;"></div>
</div>
+
+<%
+ @resource=@backup_resource
+ @project=@backup_project
+ @snapshot=@backup_snapshot
+ @dashboard_configuration=@backup_dashboard_configuration
+%>