]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-3825 support periods
authorSimon Brandhof <simon.brandhof@gmail.com>
Wed, 28 Nov 2012 13:56:18 +0000 (14:56 +0100)
committerSimon Brandhof <simon.brandhof@gmail.com>
Wed, 28 Nov 2012 13:56:18 +0000 (14:56 +0100)
sonar-core/src/main/java/org/sonar/core/measure/MeasureFilter.java
sonar-server/src/main/webapp/WEB-INF/app/helpers/application_helper.rb
sonar-server/src/main/webapp/WEB-INF/app/helpers/measures_helper.rb
sonar-server/src/main/webapp/WEB-INF/app/models/measure_filter_display_list.rb
sonar-server/src/main/webapp/WEB-INF/app/views/measures/_display_list.html.erb

index 41f987dd57944a1c8b38f4e3ac0ee7cfcad55a6a..cbe358cb792ea20342c2f9dfcb43cae9c99ca5ce 100644 (file)
@@ -183,7 +183,7 @@ public class MeasureFilter {
 
   @VisibleForTesting
   static List<String> sanitize(@Nullable List<String> list) {
-    return isBlank(list) ? Collections.<String>emptyList() : list;
+    return isBlank(list) ? Collections.<String>emptyList() : Lists.newArrayList(list);
   }
 
   private static boolean isBlank(@Nullable List<String> list) {
index a4c30ef5227ab7f6fde46ef34af7755886dd33b6..76bc0264591d828f341927f11e1c592c0864d378 100644 (file)
@@ -286,10 +286,10 @@ module ApplicationHelper
     if resource.display_dashboard?
       if options[:dashboard]
         link_to(name || resource.name, params.merge({:controller => 'dashboard', :action => 'index', :id => resource.id, :period => period_index,
-                                                              :tab => options[:tab], :rule => options[:rule]}), :title => options[:title])
+                                                     :tab => options[:tab], :rule => options[:rule]}), :title => options[:title])
       elsif options[:filter]
         link_to(name || resource.name, params.merge({:controller => 'dashboard', :action => 'index', :did => nil, :id => resource.id, :period => period_index,
-                                                                :tab => options[:tab], :rule => options[:rule]}), :title => options[:title])
+                                                     :tab => options[:tab], :rule => options[:rule]}), :title => options[:title])
       else
         # stay on the same page (for example components)
         link_to(name || resource.name, params.merge({:id => resource.id, :period => period_index, :tab => options[:tab], :rule => options[:rule]}), :title => options[:title])
@@ -571,7 +571,7 @@ module ApplicationHelper
     html += "\">"
     html += message('reviews.filtered_by.' + param_name)
     html += "<a href=\""
-    html += url_for params.reject{|key, value| key==param_name}
+    html += url_for params.reject { |key, value| key==param_name }
     html += "\" title=\""
     html += message('reviews.remove_this_filter')
     html += "\">X</a></span>"
@@ -611,20 +611,24 @@ module ApplicationHelper
 
       # Compare the non-digits
       case (chars1 <=> chars2)
-      when 0
-        # Non-digits are the same, compare the digits...
-        # If either number begins with a zero, then compare
-        # alphabetically, otherwise compare numerically
-        if (num1[0] != 48) and (num2[0] != 48)
-          num1, num2 = num1.to_i, num2.to_i
-        end
+        when 0
+          # Non-digits are the same, compare the digits...
+          # If either number begins with a zero, then compare
+          # alphabetically, otherwise compare numerically
+          if (num1[0] != 48) and (num2[0] != 48)
+            num1, num2 = num1.to_i, num2.to_i
+          end
 
-        case (num1 <=> num2)
-        when -1 then return -1
-        when 1 then return 1
-        end
-      when -1 then return -1
-      when 1 then return 1
+          case (num1 <=> num2)
+            when -1 then
+              return -1
+            when 1 then
+              return 1
+          end
+        when -1 then
+          return -1
+        when 1 then
+          return 1
       end # case
 
     end # while
@@ -664,17 +668,17 @@ module ApplicationHelper
 
     min_length = 3 # see limitation in /api/resources/search
     js_options={
-        'minimumInputLength' => min_length,
-        'formatNoMatches' => "function(term){return '#{escape_javascript message('select2.noMatches')}'}",
-        'formatSearching' => "function(){return '#{escape_javascript message('select2.searching')}'}",
-        'formatInputTooShort' => "function(term, minLength){return '#{escape_javascript message('select2.tooShort', :params => [min_length])}'}"
+      'minimumInputLength' => min_length,
+      'formatNoMatches' => "function(term){return '#{escape_javascript message('select2.noMatches')}'}",
+      'formatSearching' => "function(){return '#{escape_javascript message('select2.searching')}'}",
+      'formatInputTooShort' => "function(term, minLength){return '#{escape_javascript message('select2.tooShort', :params => [min_length])}'}"
     }
     js_options['width']= "'#{width}'" if width
-    js_options['ajax']='{' + ajax_options.map{|k,v| "#{k}:#{v}"}.join(',') + '}'
+    js_options['ajax']='{' + ajax_options.map { |k, v| "#{k}:#{v}" }.join(',') + '}'
     js_options.merge!(options[:select2_options]) if options[:select2_options]
 
     html = "<input type='hidden' id='#{html_id}' name='#{name}'/>"
-    js = "$j('##{html_id}').select2({#{js_options.map{|k,v| "#{k}:#{v}"}.join(',')}});"
+    js = "$j('##{html_id}').select2({#{js_options.map { |k, v| "#{k}:#{v}" }.join(',')}});"
 
     resource = options[:selected_resource]
     if resource
@@ -694,6 +698,8 @@ module ApplicationHelper
   # * <tt>:allow_empty</tt> - If set to true, selecting a value is not mandatory
   # * <tt>:width</tt> - The width suffixed with unit, for example '300px' or '100%'. Default is '250px'
   # * <tt>:html_id</tt> - The id of the HTML element. Default is the name.
+  # * <tt>:key_prefix</tt> - Prefix added to metric keys. Default is ''
+  # * <tt>:extra_values</tt> -
   #
   def metric_select_tag(name, metrics, options={})
     width=options[:width]||'250px'
@@ -713,10 +719,21 @@ module ApplicationHelper
       select_tag_prompt=''
     end
 
-    metrics_by_domain=metrics.sort_by(&:short_name).inject({}) do |h, metric|
+    extra_values = options[:extra_values]
+    metrics_by_domain={}
+    if extra_values
+      extra_values.inject(metrics_by_domain) do |h, extra_value|
+        h['']||=[]
+        h['']<<extra_value
+        h
+      end
+    end
+
+    key_prefix = options[:key_prefix]||''
+    metrics.sort_by(&:short_name).inject(metrics_by_domain) do |h, metric|
       domain=metric.domain||''
       h[domain]||=[]
-      h[domain]<<[metric.short_name, metric.key]
+      h[domain]<<[metric.short_name, key_prefix + metric.key]
       h
     end
 
@@ -724,7 +741,7 @@ module ApplicationHelper
                       :multiple => options[:multiple],
                       :disabled => options[:disabled],
                       :id => html_id)
-    js = "$j('##{html_id}').select2({#{js_options.map{|k,v| "#{k}:#{v}"}.join(',')}});"
+    js = "$j('##{html_id}').select2({#{js_options.map { |k, v| "#{k}:#{v}" }.join(',')}});"
     "#{html}<script>#{js}</script>"
   end
 
@@ -752,7 +769,7 @@ module ApplicationHelper
     url += "&tk=#{u title_key}" if title_key
     if message_key
       url += "&mk=#{u message_key}&"
-      url += message_params.map{|p| "mp[]=#{u p}"}.join('&') if message_params
+      url += message_params.map { |p| "mp[]=#{u p}" }.join('&') if message_params
     end
     if button_key
       url += "&bk=#{u button_key}"
index 7d27e92ed4f770dc5b921c87dcc0b9178fe0dfe6..fce2d6dcb0ab98928f4732a7be375e5e705a61f4 100644 (file)
 module MeasuresHelper
 
   def list_column_html(filter, column)
-
     if column.sort?
       html = link_to_function(h(column.name), "reloadParameters({asc:'#{(!filter.sort_asc?).to_s}', sort:'#{column.key}'})")
     else
       html=h(column.name)
     end
+    if column.period
+      html += "<br><span class='note'>Period #{column.period}</small>"
+    end
     if filter.sort_key==column.key
       html << (filter.sort_asc? ? image_tag("asc12.png") : image_tag("desc12.png"))
     end
@@ -34,7 +36,13 @@ module MeasuresHelper
 
   def list_cell_html(column, result)
     if column.metric
-      format_measure(result.measure(column.metric))
+      measure = result.measure(column.metric)
+      if column.period
+        format_variation(measure, :index => column.period, :style => 'light')
+      else
+        format_measure(measure)
+      end
+
     elsif column.key=='name'
       "#{qualifier_icon(result.snapshot)} #{link_to(result.snapshot.resource.name(true), {:controller => 'dashboard', :id => result.snapshot.resource_id}, :title => result.snapshot.resource.key)}"
     elsif column.key=='short_name'
@@ -82,4 +90,28 @@ module MeasuresHelper
     end
     size.to_i
   end
+
+  def period_names
+    p1=Property.value('sonar.timemachine.period1', nil, 'previous_analysis')
+    p2=Property.value('sonar.timemachine.period2', nil, '5')
+    p3=Property.value('sonar.timemachine.period3', nil, '30')
+    [period_name(p1), period_name(p2), period_name(p3)]
+  end
+
+  def period_name(property)
+    if property=='previous_analysis'
+      message('delta_since_previous_analysis')
+    elsif property=='previous_version'
+      message('delta_since_previous_version')
+    elsif property =~ /^[\d]+(\.[\d]+){0,1}$/
+      # is integer
+      message('delta_over_x_days', :params => property)
+    elsif property =~ /\d{4}-\d{2}-\d{2}/
+      message('delta_since', :params => property)
+    elsif !property.blank?
+      message('delta_since_version', :params => property)
+    else
+      nil
+    end
+  end
 end
index 90bdfe2188eee8ec5370867bd3be03910049b296..7c2077324f1393880f55fe1500997d2f1aca5ad3 100644 (file)
@@ -22,12 +22,15 @@ class MeasureFilterDisplayList < MeasureFilterDisplay
   KEY = :list
 
   class Column
-    attr_reader :key, :metric
+    attr_reader :key, :metric, :period
 
     def initialize(key)
       @key = key
-      metric_key = @key.split(':')[1]
-      @metric = Metric.by_key(metric_key) if metric_key
+      fields = @key.split(':')
+      if fields.size>=2 && fields[0]=='metric'
+        @metric = Metric.by_key(fields[1])
+        @period = fields[2].to_i if fields.size>=3
+      end
     end
 
     def name
@@ -40,10 +43,10 @@ class MeasureFilterDisplayList < MeasureFilterDisplay
 
     def align
       @align ||=
-          begin
-            # by default is table cells are left-aligned
-            (@key=='name' || @key=='short_name' || @key=='description') ? '' : 'right'
-          end
+        begin
+          # by default is table cells are left-aligned
+          (@key=='name' || @key=='short_name' || @key=='description') ? '' : 'right'
+        end
     end
 
     def sort?
@@ -80,7 +83,8 @@ class MeasureFilterDisplayList < MeasureFilterDisplay
   end
 
   PROPERTY_KEYS = Set.new(['cols', 'sort', 'asc', 'pageSize'])
+
   def url_params
-    @filter.criteria.select{ |k,v| PROPERTY_KEYS.include?(k)}
+    @filter.criteria.select { |k, v| PROPERTY_KEYS.include?(k) }
   end
 end
index 692b37f3a11f00faf09246ca9a3e73e6d4074eb7..322041be554ec3ad76004c4cb5581e34993f280a 100644 (file)
   <table class="data width100 admin">
     <tr>
       <td>
-        <%= metric_select_tag 'metric', Metric.all.reject { |m| m.data? }, :html_id => 'select-metric', :allow_empty => true -%>
-        <button id="add-metric" disabled>Add</button>
+        <%= metric_select_tag 'metric', Metric.all.reject { |m| m.data? },
+                              :html_id => 'select-metric',
+                              :allow_empty => true,
+                              :key_prefix => 'metric:',
+                              :extra_values => [['Name', 'name'], ['Short Name', 'short_name'], ['Description', 'description'], ['Version', 'version']] -%>
+        <select id="select-period" style="display: none;">
+          <option value="">Value</option>
+          <% period_names.each_with_index do |period_name, index| %>
+            <option value="<%= index + 1 -%>"><%= period_name -%></option>
+          <% end %>
+        </select>
+
+        <button id="add-metric">Add</button>
       </td>
       <td class="right">
         <a href="#" class="button" id="exit-edit">Done</a>
   </table>
   <script>
     $j("#select-metric").on("change", function (e) {
+      var selectedKey = $j("#select-metric option:selected").val();
+      if (selectedKey.indexOf('metric:') == 0) {
+        if (selectedKey.indexOf('metric:new_') == 0) {
+          $j('#select-period option :eq(0)').attr('disabled', 'disabled');
+          $j('#select-period ').val('1');
+        } else {
+          $j('#select-period option :eq(0)').removeAttr('disabled');
+          $j('#select-period').val('');
+        }
+        $j('#select-period').show();
+      } else {
+        $j('#select-period').hide();
+      }
       $j("#add-metric").removeAttr('disabled');
+
     });
     $j("#add-metric").on("click", function (e) {
-      var metric = $j("#select-metric option:selected").val();
-      cols.push('metric:' + metric);
+      var columnKey = $j("#select-metric option:selected").val();
+      var period = $j("#select-period option:selected").val();
+      if (period.length > 0) {
+        columnKey += ':' + period;
+      }
+      cols.push(columnKey);
       window.location = removeUrlAttr(decodeURI(window.location.href), 'cols\\[\\]') + '&' + $j.map(cols,function (a) {
         return 'cols[]=' + a;
       }).join('&');