diff options
author | Fabrice Bellingard <bellingard@gmail.com> | 2011-08-25 16:29:16 +0200 |
---|---|---|
committer | Fabrice Bellingard <bellingard@gmail.com> | 2011-08-25 16:29:16 +0200 |
commit | b667702b4608edd0dc8f461a165a33cabb7e08a7 (patch) | |
tree | 6f3980543068ea8a170a4c8d2c53e9ddadb1990e /plugins | |
parent | 8a4f61072115d5c57098ae43d13dc4bba1292250 (diff) | |
download | sonarqube-b667702b4608edd0dc8f461a165a33cabb7e08a7.tar.gz sonarqube-b667702b4608edd0dc8f461a165a33cabb7e08a7.zip |
SONAR-2701 New "Time Machine" widget
Allows to display measures of required metrics by past version
Diffstat (limited to 'plugins')
5 files changed, 180 insertions, 4 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 4a30f0daac8..fd6b705e6bc 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 @@ -215,6 +215,7 @@ public class CorePlugin extends SonarPlugin { extensions.add(EventsWidget.class); extensions.add(CustomMeasuresWidget.class); extensions.add(TimelineWidget.class); + extensions.add(TimeMachineWidget.class); // chart extensions.add(XradarChart.class); diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/TimeMachineWidget.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/TimeMachineWidget.java new file mode 100644 index 00000000000..5d8af7e9a35 --- /dev/null +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/TimeMachineWidget.java @@ -0,0 +1,58 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 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.WidgetProperties; +import org.sonar.api.web.WidgetProperty; +import org.sonar.api.web.WidgetPropertyType; + +@WidgetProperties( + { + @WidgetProperty(key = "numberOfVersions", type = WidgetPropertyType.INTEGER, defaultValue = "4"), + @WidgetProperty(key = "displaySparkLine", type = WidgetPropertyType.BOOLEAN), + @WidgetProperty(key = "metric1", type = WidgetPropertyType.METRIC, defaultValue = "ncloc"), + @WidgetProperty(key = "metric2", type = WidgetPropertyType.METRIC), + @WidgetProperty(key = "metric3", type = WidgetPropertyType.METRIC), + @WidgetProperty(key = "metric4", type = WidgetPropertyType.METRIC), + @WidgetProperty(key = "metric5", type = WidgetPropertyType.METRIC), + @WidgetProperty(key = "metric6", type = WidgetPropertyType.METRIC), + @WidgetProperty(key = "metric7", type = WidgetPropertyType.METRIC), + @WidgetProperty(key = "metric8", type = WidgetPropertyType.METRIC), + @WidgetProperty(key = "metric9", type = WidgetPropertyType.METRIC), + @WidgetProperty(key = "metric10", type = WidgetPropertyType.METRIC) + } +) +public class TimeMachineWidget extends AbstractRubyTemplate implements RubyRailsWidget { + public String getId() { + return "time_machine"; + } + + public String getTitle() { + return "Time Machine"; + } + + @Override + protected String getTemplatePath() { + return "/org/sonar/plugins/core/widgets/time_machine.html.erb"; + //return "/Users/fbellingard/Documents/Sonar/repos/sonar/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/time_machine.html.erb"; + } +}
\ No newline at end of file diff --git a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/time_machine.html.erb b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/time_machine.html.erb new file mode 100644 index 00000000000..e1d0aee470f --- /dev/null +++ b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/time_machine.html.erb @@ -0,0 +1,114 @@ +<% + # Retrieve widget settings + metric_ids = [] + (1..10).each do |index| + metric=widget_properties["metric#{index}"] + if metric + metric_ids << metric.id + end + end + if metric_ids.empty? + # No metric has been selected, it's the first time the widget is displayed: 'ncloc' is the default metric + ncloc = Metric.find(:first, :conditions => "name = 'ncloc'") + metric_ids << ncloc.id + end + numberOfVersions = widget_properties["numberOfVersions"].to_i == 0 ? 4 : widget_properties["numberOfVersions"].to_i + displaySparkLine = widget_properties["displaySparkLine"] + + # Retrieve the measures for each metric on each snapshot + options = {} + from_date = dashboard_configuration.from_datetime + if from_date + options[:from] = from_date + end + snapshots=Snapshot.for_timemachine_widget(@resource, numberOfVersions, options) + sids = snapshots.collect{|s| s.id}.uniq + measures=ProjectMeasure.find(:all, :conditions => {:snapshot_id => sids, :metric_id => metric_ids}) + + # And prepare the rows to display + snapshot_by_id={} + snapshots.each do |s| + snapshot_by_id[s.id]=s + end + rows_by_metric_id={} + rows=[] + measures.each do |measure| + next unless measure.metric + + if measure.metric.timemachine? && (measure.value || measure.text_value) + row=rows_by_metric_id[measure.metric_id] + unless row + row=Sonar::TimemachineRow.new(measure.metric) + rows<<row + rows_by_metric_id[measure.metric_id]=row + end + + #optimization : avoid eager loading of snapshots + measure.snapshot=snapshot_by_id[measure.snapshot_id] + row.add_measure(measure) + end + end + + rows.sort! +%> + +<div class="widget-matrix"> + +<table class="widget-matrix"> + + <thead> + <tr> + <th valign="top" nowrap="nowrap" style="background-color: #FFFFFF; border: 0px;"> + </th> + <% snapshots.each do |snapshot| %> + <th nowrap="nowrap" align="right" valign="top"> + <%= l snapshot.created_at.to_date %> + <br/> + <% snapshot.user_events.each do |event| %> + <b><%= event.name %></b> + <br/> + <% end %> + </th> + <% end %> + <th> </th> + </tr> + </thead> + + <tbody> + <% + previous_domain='' + rows.select{|row| row.metric.val_type != Metric::VALUE_TYPE_DISTRIB}.each do |row| + if previous_domain != row.domain + %> + <tr> + <td class="title" colspan="<%= snapshots.size + 2 -%>"><%= row.domain %></td> + </tr> + <% + end + previous_domain = row.domain + %> + <tr class="<%= cycle("even", "odd", :name => row.domain) -%>"> + <td width="1%" nowrap="nowrap" valign="top"> + <%= row.metric.short_name %> + </td> + <% + snapshots.each do |snapshot| + measure=row.measure(snapshot) + %> + <td align="right" width="1%" nowrap="nowrap"><%= format_measure(measure, :skip_span_id => true) %></td> + <% end %> + <td> + <% + sparkline_url=row.sparkline_url + if displaySparkLine && sparkline_url + %> + <%= image_tag(sparkline_url) %> + <% end %> + </td> + </tr> + <% end %> + </tbody> + +</table> + +</div>
\ No newline at end of file diff --git a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/timeline.html.erb b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/timeline.html.erb index ad44fbac17a..806d77f7a7c 100644 --- a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/timeline.html.erb +++ b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/timeline.html.erb @@ -1,5 +1,6 @@ <%= javascript_include_tag 'protovis-sonar' %> <% + # Retrieve widget settings metric_data_map = {} metric_name_map = {} (1..3).each do |index| @@ -11,10 +12,11 @@ end if metric_data_map.empty? # No metric has been selected, it's the first time the widget is displayed: 'ncloc' is the default metric - ncloc = Metric.find(:all, :conditions => "name = 'ncloc'").first + ncloc = Metric.find(:first, :conditions => "name = 'ncloc'") metric_data_map[ncloc.id] = [] metric_name_map[ncloc.id] = message('metric.ncloc.name') end + chartHeight = widget_properties["chartHeight"].to_i == 0 ? "null" : widget_properties["chartHeight"] # Retrieve metric trend information options = {} @@ -98,9 +100,7 @@ js_translations = "{" js_translations += "\"date\":\"" + message("date") + "\"" js_translations += "}" - - # Check if the widget height was specified - chartHeight = widget_properties["chartHeight"].to_i == 0 ? "null" : widget_properties["chartHeight"] + %> <% if widget_properties["chartTitle"] %> diff --git a/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/core.properties b/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/core.properties index c0754fd8e2f..97560a509c0 100644 --- a/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/core.properties +++ b/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/core.properties @@ -514,6 +514,9 @@ widget.timeline.name=Timeline widget.timeline.description=Displays up to 3 metrics on a history chart. widget.timeline.timeline_not_displayed=The timeline won't be displayed as currently only 1 snapshot is available. +widget.time_machine.name=Time Machine +widget.time_machine.description=Displays up to 10 metrics in a table, showing their value for a specified number of past snapshots. + widget.ckjm.name=Chidamber & Kemerer widget.ckjm.description=Reports on LCOM4 and RFC average and distribution. widget.ckjm.lcom4=LCOM4 |