]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-1956 improve filters in order to display variations
authorsimonbrandhof <simon.brandhof@gmail.com>
Fri, 10 Dec 2010 13:37:09 +0000 (13:37 +0000)
committersimonbrandhof <simon.brandhof@gmail.com>
Fri, 10 Dec 2010 13:37:09 +0000 (13:37 +0000)
16 files changed:
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/PastSnapshotFinder.java
sonar-server/src/main/java/org/sonar/server/filters/Filter.java
sonar-server/src/main/java/org/sonar/server/filters/MeasureCriterion.java
sonar-server/src/main/webapp/WEB-INF/app/controllers/filters_controller.rb
sonar-server/src/main/webapp/WEB-INF/app/helpers/filters_helper.rb
sonar-server/src/main/webapp/WEB-INF/app/models/criterion.rb
sonar-server/src/main/webapp/WEB-INF/app/models/filter_context.rb [new file with mode: 0644]
sonar-server/src/main/webapp/WEB-INF/app/models/filter_result.rb [deleted file]
sonar-server/src/main/webapp/WEB-INF/app/models/property.rb
sonar-server/src/main/webapp/WEB-INF/app/views/filters/_criterion.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/filters/_list.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/filters/index.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/filters/new.html.erb
sonar-server/src/main/webapp/WEB-INF/db/migrate/168_add_variations_to_filters.rb
sonar-server/src/main/webapp/images/trend-up.png
sonar-server/src/test/java/org/sonar/server/filters/FilterExecutorTest.java

index 22367050af1f094ce8857317bc6ba4d8397770aa..541aed3fbc8803d2c397372d7a62641d52df4a4b 100644 (file)
@@ -29,6 +29,9 @@ import java.util.Date;
 
 public class PastSnapshotFinder implements BatchExtension {
 
+  /**
+   * IMPORTANT : please update default values in the ruby side too. See app/helpers/FiltersHelper.rb
+   */
   public static final String DEFAULT_VALUE_1 = PastSnapshotFinderByPreviousAnalysis.MODE;
   public static final String DEFAULT_VALUE_2 = "5";
   public static final String DEFAULT_VALUE_3 = "30";
index 4b3a456a8a4e6fadd08b0dc3c987bc64fd13d648..c2d92af8d5b353415cc33b15937b2fc74b8e7a4f 100644 (file)
@@ -254,8 +254,8 @@ public class Filter {
     return this;
   }
 
-  public Filter createMeasureCriterionOnValue(Integer metricId, String operator, Double value) {
-    this.measureCriteria.add(new MeasureCriterion(metricId, operator, value));
+  public Filter createMeasureCriterionOnValue(Integer metricId, String operator, Double value, Boolean variation) {
+    this.measureCriteria.add(new MeasureCriterion(metricId, operator, value, variation));
     return this;
   }
 
index eb3aa5e7d7a9b54a7f44bcd670f87f4dd69ef2b0..4c2a9fd15062663ba53df47bee70e955c165d5fd 100644 (file)
@@ -19,7 +19,7 @@
  */
 package org.sonar.server.filters;
 
-import org.apache.commons.lang.builder.ToStringBuilder;
+import org.apache.commons.lang.builder.ReflectionToStringBuilder;
 import org.apache.commons.lang.builder.ToStringStyle;
 
 public class MeasureCriterion {
@@ -27,11 +27,13 @@ public class MeasureCriterion {
   private Integer metricId;
   private String operator;
   private Double value;
+  private Boolean variation;
 
-  public MeasureCriterion(Integer metricId, String operator, Double value) {
+  public MeasureCriterion(Integer metricId, String operator, Double value, Boolean variation) {
     this.metricId = metricId;
     this.operator = operator;
     this.value = value;
+    this.variation = variation;
   }
 
   public Integer getMetricId() {
@@ -58,12 +60,17 @@ public class MeasureCriterion {
     this.value = value;
   }
 
+  public Boolean getVariation() {
+    return variation;
+  }
+
+  public MeasureCriterion setVariation(Boolean b) {
+    this.variation = b;
+    return this;
+  }
+
   @Override
   public String toString() {
-    return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
-        .append("metricId", metricId)
-        .append("operator", operator)
-        .append("value", value)
-        .toString();
+    return new ReflectionToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).toString();
   }
 }
index 5315af9b5ef99dde03ffb606d0975e0b566aa369..69644b74a1ff5c7010fe7bb68c716485ad401ba8 100644 (file)
@@ -86,8 +86,9 @@ class FiltersController < ApplicationController
       return access_denied
     end
 
-    @variation_index=params[:var].to_i
-    @data=execute_filter(@filter, current_user, params)
+    options=params
+    options[:user]=current_user
+    @filter_context=execute_filter(FilterContext.new(@filter, options))
     render :action => 'new'
   end
 
@@ -398,11 +399,14 @@ class FiltersController < ApplicationController
     params[:metric_ids]=[@size_metric, @color_metric]
 
     @filter.sorted_column=FilterColumn.new('family' => 'metric', :kee => @size_metric.key, :sort_direction => (@size_metric.direction>=0 ? 'ASC' : 'DESC'))
-    @data=execute_filter(@filter, current_user, params)
-    
+
+    options=params
+    options[:user]=current_user
+    @filter_context=execute_filter(FilterContext.new(@filter, options))
+
     @width=(params[:width]||'800').to_i
     @height=(params[:height]||'500').to_i
-    @treemap=Sonar::Treemap.new(@data.measures_by_snapshot, @width, @height, @size_metric, @color_metric)
+    @treemap=Sonar::Treemap.new(@filter_context.measures_by_snapshot, @width, @height, @size_metric, @color_metric)
     render :action => "treemap", :layout => false
   end
 
@@ -481,7 +485,9 @@ class FiltersController < ApplicationController
     if @active
       @filter=@active.filter
       unless @filter.ajax_loading?
-        @data=execute_filter(@filter, current_user, params)
+        options=params
+        options[:user]=current_user
+        @filter_context=execute_filter(FilterContext.new(@filter, options))
         load_masterproject() if @filter.projects_homepage?
       end
     end
index 3aefd4295f9d56b75d10a1ecb6da4a57517c40b4..35bea1ad09146f53e2e67b439aa2fc98dd26bf46 100644 (file)
@@ -19,7 +19,8 @@
 #
 module FiltersHelper
 
-  def execute_filter(filter, user=nil, options={})
+  def execute_filter(filter_context)
+    filter=filter_context.filter
     java_filter=Java::OrgSonarServerFilters::Filter.new
 
     #----- FILTER ON RESOURCES
@@ -33,7 +34,7 @@ module FiltersHelper
     end
 
     if filter.favourites
-      java_filter.setFavouriteIds((user ? user.favourite_ids : []).to_java(:Integer))
+      java_filter.setFavouriteIds((filter_context.user ? user.favourite_ids : []).to_java(:Integer))
     end
 
     date_criterion=filter.criterion('date')
@@ -66,13 +67,13 @@ module FiltersHelper
 
     #----- FILTER ON MEASURES
     filter.measure_criteria.each do |c|
-      java_filter.createMeasureCriterionOnValue(c.metric.id, c.operator, c.value)
+      java_filter.createMeasureCriterionOnValue(c.metric.id, c.operator, c.value, c.variation)
     end
 
 
     #----- SORTED COLUMN
-    if options[:sort]
-      filter.sorted_column=options[:sort].to_i
+    if filter_context.sorted_column_id
+      filter.sorted_column=filter_context.sorted_column_id
     end
     if filter.sorted_column.on_name?
       java_filter.setSortedByName()
@@ -90,25 +91,21 @@ module FiltersHelper
 
 
     #----- SORTING DIRECTION
-    if options[:asc]
-      filter.sorted_column.ascending=(options[:asc]=='true')
+    if filter_context.ascending_sort
+      filter.sorted_column.ascending=filter_context.ascending_sort
     end
     java_filter.setAscendingSort(filter.sorted_column.ascending?)
 
 
     #----- VARIATION
-    variation_index = (options[:var] ? options[:var].to_i : filter.variation_index)
-    java_filter.setSortedVariationIndex(variation_index)
+    java_filter.setSortedVariationIndex(filter_context.variation_index)
 
     #----- EXECUTION
     java_result=java_facade.execute_filter(java_filter)
     snapshot_ids=extract_snapshot_ids(java_result.getRows())
 
-
-
-    options[:snapshot_ids]=snapshot_ids
-    options[:security_exclusions]=(snapshot_ids.size < java_result.size())
-    FilterResult.new(filter, options)
+    has_security_exclusions=(snapshot_ids.size < java_result.size())
+    filter_context.process_results(snapshot_ids, has_security_exclusions)
   end
 
   def column_title(column, filter)
@@ -156,9 +153,30 @@ module FiltersHelper
     end
   end
 
+  def period_names
+    p1=Property.value('sonar.timemachine.variation1', nil, 'previous_analysis')
+    p2=Property.value('sonar.timemachine.variation2', nil, '5')
+    p3=Property.value('sonar.timemachine.variation3', nil, '30')
+    [period_name(p1), period_name(p2), period_name(p3)]
+  end
 
   private
 
+  def period_name(property)
+    if property=='previous_analysis'
+      "Since previous analysis"
+    elsif property =~ /^[\d]+(\.[\d]+){0,1}$/
+      # is integer
+      "Previous #{property} days"
+    elsif property =~ /\d{4}-\d{2}-\d{2}/
+      "Since #{property}"
+    elsif !property.blank?
+      "Since version #{property}"
+    else
+      nil
+    end
+  end
+
   def extract_snapshot_ids(sql_rows)
     sids=[]
     project_ids=sql_rows.map{|r| r[2] ? to_integer(r[2]) : to_integer(r[1])}.compact.uniq
index d04348a79789b646c45dc0e3637c0aabb3ce0050..68eb11767f6452cb19c8dcc774442f71018eb19d 100644 (file)
@@ -79,7 +79,7 @@ class Criterion < ActiveRecord::Base
 
   def self.new_for_metric(options)
     metric=Metric.by_id(options['metric_id'])
-    new(:family => 'metric', :operator => options['operator'], :kee => (metric ? metric.name : nil), :value => options['value']
+    new(:family => 'metric', :operator => options['operator'], :kee => (metric ? metric.name : nil), :value => options['value'], :variation => (options['type']=='variation'))
   end
 
 end
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/filter_context.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/filter_context.rb
new file mode 100644 (file)
index 0000000..aa45415
--- /dev/null
@@ -0,0 +1,164 @@
+ #
+ # Sonar, entreprise quality control tool.
+ # Copyright (C) 2009 SonarSource SA
+ # 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 {library}; if not, write to the Free Software
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ #
+ class FilterContext
+  attr_accessor :filter, :page_size, :page_id, :security_exclusions, :variation_index, :user, :sorted_column_id, :ascending_sort
+
+  def initialize(filter, options={})
+    @filter = filter
+    @page_size=options[:page_size] || @filter.page_size
+    @page_id=(options[:page_id] ? options[:page_id].to_i : 1)
+    @sorted_column_id=(options[:sort].blank? ? nil : options[:sort].to_i)
+    @ascending_sort=(options[:asc].blank? ? nil : options[:asc]=='true')
+    @user=options[:user]
+    @variation_index = (options[:var] ? options[:var].to_i : filter.variation_index )
+    @metric_ids=(options[:metric_ids] || @filter.columns.map{|col| col.metric ? col.metric.id : nil}.compact.uniq)
+  end
+
+  def process_results(snapshot_ids, security_exclusions)
+    @sids=snapshot_ids
+    @security_exclusions=security_exclusions
+    
+    from=(@page_id-1) * @page_size
+    to=(@page_id*@page_size)-1
+    to=@sids.size-1 if to>=@sids.size
+
+    @measures_by_snapshot={}
+    @page_snapshots=[]
+    @snapshots_by_id={}
+    @links_by_pid={}
+    if from<@sids.size
+      #
+      # load snapshots and resources
+      #
+      @page_sids=@sids[from..to]
+      @page_snapshots=Snapshot.find(:all, :include => ['project'], :conditions => ['id in (?)', @page_sids])
+      @page_snapshots.each{|s| @snapshots_by_id[s.id]=s}
+
+      if @page_sids.size>0
+        #
+        # load measures
+        #
+        if @metric_ids.size>0
+          measures=ProjectMeasure.find(:all, :conditions => ['rule_priority is null and rule_id is null and characteristic_id is null and snapshot_id in (?)', @page_sids])
+
+          if filter.display_user_managed_metrics?
+            measures.concat(AsyncMeasureSnapshot.search(@page_sids, @metric_ids))
+          end
+
+          measures.each do |m|
+            snapshot=@snapshots_by_id[m.snapshot_id]
+            @measures_by_snapshot[snapshot]||={}
+            @measures_by_snapshot[snapshot][m.metric]=m
+          end
+        end
+
+        #
+        # load links
+        #
+        if @filter.display_links?
+          pids=@page_snapshots.map{|snapshot| snapshot.project_id}
+          ProjectLink.find(:all, :conditions => {:project_id => pids}, :order => 'link_type').each do |link|
+            @links_by_pid[link.project_id] ||= []
+            @links_by_pid[link.project_id]<<link
+          end
+        end
+      end
+    end
+    self
+  end
+
+
+  def size
+    @sids.size
+  end
+
+  def empty?
+    @page_sids.nil? || @page_sids.empty?
+  end
+
+  def page_count
+    result=@sids.size / @page_size
+    result+=1 if (@sids.size % @page_size > 0)
+    result
+  end
+
+  def page_sorted_snapshot_ids
+    @page_sids
+  end
+
+  def snapshots
+    @page_snapshots
+  end
+
+  def snapshot(sid)
+    @snapshots_by_id[sid]
+  end
+
+  def measure(snapshot, metric)
+    if metric
+      hash=@measures_by_snapshot[snapshot]
+      hash ? hash[metric] : nil
+    else
+      nil
+    end
+  end
+
+  def measures_by_snapshot
+    @measures_by_snapshot
+  end
+
+  def links(resource_id)
+    @links_by_pid[resource_id] || []
+  end
+
+  def security_exclusions?
+    @security_exclusions==true
+  end
+
+  def variation?
+    @variation_index && @variation_index>0
+  end
+
+
+
+  private
+
+  def extract_snapshot_ids(sql_rows)
+    sids=[]
+    project_ids=sql_rows.map{|r| r[2] ? to_integer(r[2]) : to_integer(r[1])}.compact.uniq
+    authorized_pids=select_authorized(:user, project_ids)
+    sql_rows.each do |row|
+      pid=(row[2] ? to_integer(row[2]) : to_integer(row[1]))
+      if authorized_pids.include?(pid)
+        sids<<to_integer(row[0])
+      end
+    end
+    sids
+  end
+
+  def to_integer(obj)
+    if obj.is_a?(Fixnum)
+      obj
+    else
+      # java.math.BigDecimal
+      obj.intValue()
+    end
+  end
+ end
\ No newline at end of file
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/filter_result.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/filter_result.rb
deleted file mode 100644 (file)
index 0a165ac..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
- #
- # Sonar, entreprise quality control tool.
- # Copyright (C) 2009 SonarSource SA
- # 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 {library}; if not, write to the Free Software
- # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
- #
- class FilterResult
-  attr_accessor :page_size, :page_id, :security_exclusions, :filter, :variation_index
-
-  def initialize(filter, options={})
-    @filter = filter
-    @page_size=options[:page_size] || @filter.page_size
-    @page_id=(options[:page_id] ? options[:page_id].to_i : 1)
-    @sids=options[:snapshot_ids]
-    @page_sids=[]
-    @security_exclusions=options[:security_exclusions]
-    @metric_ids=(options[:metric_ids] || @filter.columns.map{|col| col.metric ? col.metric.id : nil}.compact.uniq)
-    @variation_index = (options[:var].blank? ? filter.variation_index : options[:var].to_i)
-
-    from=(@page_id-1) * @page_size
-    to=(@page_id*@page_size)-1
-    to=@sids.size-1 if to>=@sids.size
-
-    @measures_by_snapshot={}
-    @page_snapshots=[]
-    @snapshots_by_id={}
-    @links_by_pid={}
-    if from<@sids.size
-      #
-      # load snapshots and resources
-      #
-      @page_sids=@sids[from..to]
-      @page_snapshots=Snapshot.find(:all, :include => ['project'], :conditions => ['id in (?)', @page_sids])
-      @page_snapshots.each{|s| @snapshots_by_id[s.id]=s}
-
-      if @page_sids.size>0
-        #
-        # load measures
-        #
-        if @metric_ids.size>0
-          measures=ProjectMeasure.find(:all, :conditions => ['rule_priority is null and rule_id is null and characteristic_id is null and snapshot_id in (?)', @page_sids])
-
-          if filter.display_user_managed_metrics?
-            measures.concat(AsyncMeasureSnapshot.search(@page_sids, @metric_ids))
-          end
-
-          measures.each do |m|
-            snapshot=@snapshots_by_id[m.snapshot_id]
-            @measures_by_snapshot[snapshot]||={}
-            @measures_by_snapshot[snapshot][m.metric]=m
-          end
-        end
-
-        #
-        # load links
-        #
-        if @filter.display_links?
-          pids=@page_snapshots.map{|snapshot| snapshot.project_id}
-          ProjectLink.find(:all, :conditions => {:project_id => pids}, :order => 'link_type').each do |link|
-            @links_by_pid[link.project_id] ||= []
-            @links_by_pid[link.project_id]<<link
-          end
-        end
-      end
-    end
-  end
-
-  def size
-    @sids.size
-  end
-
-  def empty?
-    @page_sids.empty?
-  end
-
-  def page_count
-    result=@sids.size / @page_size
-    result+=1 if (@sids.size % @page_size > 0)
-    result
-  end
-
-  def page_sorted_snapshot_ids
-    @page_sids
-  end
-
-  def snapshots
-    @page_snapshots
-  end
-
-  def snapshot(sid)
-    @snapshots_by_id[sid]
-  end
-
-  def measure(snapshot, metric)
-    if metric
-      hash=@measures_by_snapshot[snapshot]
-      hash ? hash[metric] : nil
-    else
-      nil
-    end
-  end
-
-  def measures_by_snapshot
-    @measures_by_snapshot
-  end
-
-  def links(resource_id)
-    @links_by_pid[resource_id] || []
-  end
-
-  def security_exclusions?
-    @security_exclusions==true
-  end
-
-  def variation?
-    @variation_index && @variation_index>0
-  end
- end
\ No newline at end of file
index 978b98509a92fd061b9b56ea21bedffdef57e789..350882982270c74eacb9ce701e1ad49e2184f5b5 100644 (file)
@@ -35,7 +35,6 @@ class Property < ActiveRecord::Base
     hash
   end
 
-
   def self.value(key, resource_id=nil, default_value=nil)
     prop=Property.find(:first, :conditions => {'prop_key' => key, 'resource_id' => resource_id, 'user_id' => nil})
     prop ? prop.text_value : default_value
index c419bd583081d8b9a07145093e03d94ce615337f..93067046dda634ddc5151b0486489ca58d31f25c 100644 (file)
@@ -3,6 +3,7 @@
     Form.Element.clear('metric-' + id);
     Form.Element.clear('op-' + id);
     Form.Element.clear('val-' + id);
+    Form.Element.clear('type-' + id);
   }
 </script>
 <select name="criteria[<%= id -%>][metric_id]" id="metric-<%= id -%>">
     </optgroup>
   <% end %>
 </select>
+<select name="criteria[<%= id -%>][type]" id="type-<%= id -%>">
+    <option value="value" <%= 'selected' unless (criterion && criterion.variation) -%>>Value</option>
+    <option value="variation" <%= 'selected' if criterion && criterion.variation -%>>Variation</option>
+</select>
 <select name="criteria[<%= id -%>][operator]" id="op-<%= id -%>">
   <option value=""></option>
   <option value="<" <%= 'selected' if (criterion && criterion.operator=='<') -%>>Less than</option>
index b1a93540f36e4de9c64aa0b804f628e2dfb513bb..d6016ab67d62f4e2d994fae35a46ba6841d52f00 100644 (file)
@@ -1,12 +1,12 @@
-<% filter=data.filter %>
+<% filter=@filter_context.filter %>
 <div>
-Periods:
+Period:
 <form action="<%= url_for :overwrite_params => {:var => nil} -%>" style="display: inline" method="get">
   <select name="var" onchange="submit()" class="small">
       <option value="">None</option>
-      <option value="1" <%= 'selected' if data.variation_index==1 -%>>Period 1</option>
-      <option value="2" <%= 'selected' if data.variation_index==2 -%>>Period 2</option>
-      <option value="3" <%= 'selected' if data.variation_index==3 -%>>Period 3</option>
+      <% period_names.each_with_index do |name, index| %>
+         <option value="<%= index+1 -%>" <%= 'selected' if @filter_context.variation_index==index+1 -%>><%= name -%></value>
+      <% end %>
   </select>
 </form>
 
@@ -36,15 +36,15 @@ Periods:
   <tfoot>
     <tr>
       <td colspan="<%= filter.columns.size + 1 -%>">
-        <span id="results_count"><%= pluralize(data.size, 'result') %></span>
+        <span id="results_count"><%= pluralize(@filter_context.size, 'result') %></span>
 
-        <% if data.page_count>1 %>
+        <% if @filter_context.page_count>1 %>
           |
-          <%= link_to_if data.page_id>1, 'previous', {:overwrite_params => {:page_id => data.page_id-1}} %>
-          <% for index in 1..data.page_count %>
-            <%= link_to_unless index==data.page_id, index.to_s, {:overwrite_params => {:page_id => index}} %>
+          <%= link_to_if @filter_context.page_id>1, 'previous', {:overwrite_params => {:page_id => @filter_context.page_id-1}} %>
+          <% for index in 1..@filter_context.page_count %>
+            <%= link_to_unless index==@filter_context.page_id, index.to_s, {:overwrite_params => {:page_id => index}} %>
           <% end %>
-          <%= link_to_if data.page_id<data.page_count, 'next', {:overwrite_params => {:page_id => 1+data.page_id}} %>
+          <%= link_to_if @filter_context.page_id<@filter_context.page_count, 'next', {:overwrite_params => {:page_id => 1+@filter_context.page_id}} %>
         <% end %>
 
         <% if @filter.projects_homepage? %>
@@ -69,26 +69,26 @@ Periods:
       <% end %>
     </tr>
   <% end %>
-  <% if data.empty? %>
+  <% if @filter_context.empty? %>
     <tr class="even"><td colspan="<%= 1+filter.columns.size -%>">No results.</td></tr>
   <% else %>
     <%
-        data.page_sorted_snapshot_ids.each do |snapshot_id|
-          snapshot=data.snapshot(snapshot_id)
+        @filter_context.page_sorted_snapshot_ids.each do |snapshot_id|
+          snapshot=@filter_context.snapshot(snapshot_id)
     %>
     <tr class="<%= cycle('even','odd') -%>">
       <td><% if logged_in? %><%= link_to_favourite(snapshot.project) -%><% end %></td>
       <% filter.columns.each do |column| %>
       <td class="<%= column_align(column) -%>">
         <% if column.on_metric?
-             measure = data.measure(snapshot, column.metric)
+             measure = @filter_context.measure(snapshot, column.metric)
         %>
           <% if column.variation %>
-            <%= format_variation(measure, :index => data.variation_index) -%>
+            <%= format_variation(measure, :index => @filter_context.variation_index) -%>
           <% else %>
             <%= format_measure(measure) -%>
-            <% if data.variation? %>
-              <%= format_variation(measure, :index => data.variation_index) -%>
+            <% if @filter_context.variation? %>
+              <%= format_variation(measure, :index => @filter_context.variation_index) -%>
             <% else %>
               <%= trend_icon(measure, :empty => true) -%>
             <% end %>
@@ -100,7 +100,7 @@ Periods:
         <% elsif column.on_date? %><%= human_short_date(snapshot.created_at) %>
         <% elsif column.on_key? %><span class="small"><%= snapshot.project.kee -%></span>
         <% elsif column.on_links?
-             data.links(snapshot.project_id).each do |link| %>
+             @filter_context.links(snapshot.project_id).each do |link| %>
           <%= link_to(image_tag(link.icon, :alt => link.name), link.href, :class => 'nolink', :popup => true) unless link.custom? %>
         <%   end
            end %>
@@ -112,7 +112,7 @@ Periods:
   </tbody>
 </table>
 <br/>
-<% if data.security_exclusions? %>
+<% if @filter_context.security_exclusions? %>
   <p class="notes">Due to security settings, some results are not being displayed.</p>
 <% end %>
 </div>
\ No newline at end of file
index 0e39d5c80adb88d278c9ac0ed06b976ef1f0597b..901852cabe5557c8134ff2509ec6bec6cb02db68 100644 (file)
@@ -1,4 +1,4 @@
 <%= render :partial => 'filters/tabs', :locals => {:selected_tab=> (@active && @active.filter ? @active.filter.id : nil) } %>
 <div class="tabs-panel">
-<%= render :partial => "filters/#{@filter.default_view}", :locals => {:data => @data, :edit_mode => false } if @filter %>
+<%= render :partial => "filters/#{@filter.default_view}", :locals => {:edit_mode => false } if @filter %>
 </div>
\ No newline at end of file
index 5678afe6d69dea8ab8fa71ea00fa2859b507caa2..9e4bda43fd51e3943054ab19f1d721ae41ae29cb 100644 (file)
@@ -104,9 +104,9 @@ table#columns td {
           <td>
             <select id="variation_index" name="variation_index">
               <option value="">None</option>
-              <option value="1" <%= 'selected' if @filter.variation_index==1 -%>>Period 1</value>
-              <option value="2" <%= 'selected' if @filter.variation_index==2 -%>>Period 2</value>
-              <option value="3" <%= 'selected' if @filter.variation_index==3 -%>>Period 3</value>
+              <% period_names.each_with_index do |name, index| %>
+                 <option value="<%= index+1 -%>" <%= 'selected' if @filter.variation_index==index+1 -%>><%= name -%></value>
+              <% end %>
             </select>
           </td>
         </tr>
@@ -180,7 +180,7 @@ $('name').focus();
 </script>
 <br/>
 
-<% if @data %>
+<% if @filter_context %>
   <h1>Display</h1>
   <div class="admin">
     <table class="form" id="view-form">
@@ -200,6 +200,6 @@ $('name').focus();
     </table>
   </div>
   <br/>
-  <%= render :partial => "filters/#{@filter.default_view}", :locals => {:data => @data, :edit_mode => true} %>
+  <%= render :partial => "filters/#{@filter.default_view}", :locals => {:edit_mode => true} %>
 <% end %>
 </div>
\ No newline at end of file
index 34a703a19b7fe4ae8c023fc2b01862f552a3d211..f55f55cc1f7064466d31fad45f339992033dc842 100644 (file)
@@ -26,6 +26,7 @@ class AddVariationsToFilters < ActiveRecord::Migration
   def self.up
     add_column :filters, :variation_index, :integer, :null => true
     add_column :filter_columns, :variation, :boolean, :null => true
+    add_column :criteria, :variation, :boolean, :null => true
   end
 
 end
index 4c8be2ecb77ec622b8033be26bd5dab87ca13e27..d7213ad67e2e1d21961d1d2734a7e9bfdb29102d 100644 (file)
Binary files a/sonar-server/src/main/webapp/images/trend-up.png and b/sonar-server/src/main/webapp/images/trend-up.png differ
index 72e2f1ca4e470d323824bc612e780650b34ffe9a..627561b4f4fe986745d03291e9654902cb0f6e2a 100644 (file)
@@ -155,7 +155,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
     FilterExecutor executor = new FilterExecutor(getSession());
     Filter filter = new Filter()
         .setQualifiers(Sets.newHashSet(Resource.QUALIFIER_CLASS))
-        .addMeasureCriterion(new MeasureCriterion(2, ">", 50.0));
+        .addMeasureCriterion(new MeasureCriterion(2, ">", 50.0, false));
 
     FilterResult result = executor.execute(filter);
     assertSnapshotIds(result, 5);
@@ -167,8 +167,8 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
     FilterExecutor executor = new FilterExecutor(getSession());
     Filter filter = new Filter()
         .setQualifiers(Sets.newHashSet(Resource.QUALIFIER_CLASS))
-        .addMeasureCriterion(new MeasureCriterion(2, ">", 50.0))
-        .addMeasureCriterion(new MeasureCriterion(1, ">", 100.0));
+        .addMeasureCriterion(new MeasureCriterion(2, ">", 50.0, false))
+        .addMeasureCriterion(new MeasureCriterion(1, ">", 100.0, false));
 
     FilterResult result = executor.execute(filter);
     assertSnapshotIds(result, 5);
@@ -180,8 +180,8 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
     FilterExecutor executor = new FilterExecutor(getSession());
     Filter filter = new Filter()
         .setQualifiers(Sets.newHashSet(Resource.QUALIFIER_CLASS))
-        .addMeasureCriterion(new MeasureCriterion(2, ">", 50.0))
-        .addMeasureCriterion(new MeasureCriterion(1, "<", 100.0));
+        .addMeasureCriterion(new MeasureCriterion(2, ">", 50.0, false))
+        .addMeasureCriterion(new MeasureCriterion(1, "<", 100.0, false));
 
     FilterResult result = executor.execute(filter);
     assertThat(result.size(), is(0));
@@ -193,8 +193,8 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
     FilterExecutor executor = new FilterExecutor(getSession());
     Filter filter = new Filter()
         .setQualifiers(Sets.newHashSet(Resource.QUALIFIER_CLASS))
-        .addMeasureCriterion(new MeasureCriterion(2, ">", 5.0))
-        .addMeasureCriterion(new MeasureCriterion(1, ">", 5.0))
+        .addMeasureCriterion(new MeasureCriterion(2, ">", 5.0, false))
+        .addMeasureCriterion(new MeasureCriterion(1, ">", 5.0, false))
         .setSortedMetricId(2); // sort by coverage
 
     FilterResult result = executor.execute(filter);
@@ -207,8 +207,8 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
     FilterExecutor executor = new FilterExecutor(getSession());
     Filter filter = new Filter()
         .setQualifiers(Sets.newHashSet(Resource.QUALIFIER_CLASS))
-        .addMeasureCriterion(new MeasureCriterion(2, ">", 5.0)) // filter on coverage
-        .addMeasureCriterion(new MeasureCriterion(1, ">", 5.0)) // filter on lines
+        .addMeasureCriterion(new MeasureCriterion(2, ">", 5.0, false)) // filter on coverage
+        .addMeasureCriterion(new MeasureCriterion(1, ">", 5.0, false)) // filter on lines
         .setSortedMetricId(2) // sort by coverage
         .setAscendingSort(false);
 
@@ -238,7 +238,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
     FilterExecutor executor = new FilterExecutor(getSession());
     Filter filter = new Filter()
         .setQualifiers(Sets.newHashSet(Resource.QUALIFIER_CLASS))
-        .addMeasureCriterion(new MeasureCriterion(3, ">", 0.0)); // filter on duplicated lines
+        .addMeasureCriterion(new MeasureCriterion(3, ">", 0.0, false)); // filter on duplicated lines
 
     FilterResult result = executor.execute(filter);
     assertSnapshotIds(result, 6);
@@ -250,8 +250,8 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
     FilterExecutor executor = new FilterExecutor(getSession());
     Filter filter = new Filter()
         .setQualifiers(Sets.newHashSet(Resource.QUALIFIER_CLASS))
-        .addMeasureCriterion(new MeasureCriterion(1, ">", 0.0)) // filter on lines
-        .addMeasureCriterion(new MeasureCriterion(3, ">", 0.0)); // filter on duplicated lines
+        .addMeasureCriterion(new MeasureCriterion(1, ">", 0.0, false)) // filter on lines
+        .addMeasureCriterion(new MeasureCriterion(3, ">", 0.0, false)); // filter on duplicated lines
 
     FilterResult result = executor.execute(filter);
     assertSnapshotIds(result, 6);
@@ -275,7 +275,7 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
     FilterExecutor executor = new FilterExecutor(getSession());
     Filter filter = new Filter()
         .setQualifiers(Sets.newHashSet(Resource.QUALIFIER_CLASS))
-        .addMeasureCriterion(new MeasureCriterion(1, ">", 0.0)) // lines > 0
+        .addMeasureCriterion(new MeasureCriterion(1, ">", 0.0, false)) // lines > 0
         .setSortedMetricId(2); // sort by coverage
 
     FilterResult result = executor.execute(filter);
@@ -288,8 +288,8 @@ public class FilterExecutorTest extends AbstractDbUnitTestCase {
     FilterExecutor executor = new FilterExecutor(getSession());
     Filter filter = new Filter()
         .setQualifiers(Sets.newHashSet(Resource.QUALIFIER_CLASS))
-        .addMeasureCriterion(new MeasureCriterion(1, ">", 400.0)) // lines > 400
-        .addMeasureCriterion(new MeasureCriterion(1, "<", 600.0)); // lines > 400
+        .addMeasureCriterion(new MeasureCriterion(1, ">", 400.0, false)) // lines > 400
+        .addMeasureCriterion(new MeasureCriterion(1, "<", 600.0, false)); // lines > 400
 
     FilterResult result = executor.execute(filter);
     assertSnapshotIds(result, 5);