]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-1927 Implement a Global Widget that can display Complexity of a given project
authorDavid Gageot <david@gageot.net>
Wed, 9 May 2012 08:31:33 +0000 (10:31 +0200)
committerDavid Gageot <david@gageot.net>
Wed, 9 May 2012 09:22:55 +0000 (11:22 +0200)
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/TestComplexityWidget.java [new file with mode: 0644]
plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/test_complexity.html.erb [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/web/WidgetPropertyType.java
sonar-server/src/main/webapp/WEB-INF/app/helpers/widget_properties_helper.rb
sonar-server/src/main/webapp/WEB-INF/app/models/widget_property.rb
sonar-server/src/main/webapp/WEB-INF/app/views/dashboard/_configure_widget.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/dashboard/_widget.html.erb

index 2541173c0513b830304bc8be3e4f53e7cbd925e1..e9ac361baa90edd0cc4584f87430ef84b39ddf44 100644 (file)
@@ -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 (file)
index 0000000..1a5865a
--- /dev/null
@@ -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 (file)
index 0000000..3eb807b
--- /dev/null
@@ -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 %>
index 7be2caf8b2c4cd304b900560f2034f80afddc50c..a514287a388b891571f50fb2dbdf4978b516dcd3 100644 (file)
@@ -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
 }
index 277209e5b875b6a6eae737a9e0f521016f513e97..bf1e4792e4d5b74b1f91ab34c658f0616af20f3a 100644 (file)
@@ -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
index a26e8e5dfcb61fa545d7fa916933eb6a92ebbdfa..114b1440263df57324a87afbcc59a7e1c197c940 100644 (file)
@@ -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
index 61d451600386bbfec94c4f62c1d7c207383cc2c5..812e15e3d9940a4cb70f6e7d5e20c94ee53dff12 100644 (file)
@@ -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
+%>
+
 <%
    begin
      widget_body=render :inline => widget.java_definition.getTarget().getTemplate(), :locals => {:widget_properties => widget.properties_as_hash, :widget => widget, :dashboard_configuration => @dashboard_configuration}
   <div style="clear: both;"></div>
 </div>
 
+<%
+   @resource=@backup_resource
+   @project=@backup_project
+   @snapshot=@backup_snapshot
+   @dashboard_configuration=@backup_dashboard_configuration
+%>
+
+
index 035b4a87c949f1af92fe3ee9302f6f0e3cd04889..474737e744b347b5c3f63e92fd62697ad796e924 100644 (file)
@@ -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
   <% end %>
   <div style="clear: both;"></div>
 </div>
+
+<%
+   @resource=@backup_resource
+   @project=@backup_project
+   @snapshot=@backup_snapshot
+   @dashboard_configuration=@backup_dashboard_configuration
+%>