]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-3246 Provide "zoom in/zoom out" feature in the Filter Treemap component
authorSimon Brandhof <simon.brandhof@gmail.com>
Wed, 8 Feb 2012 17:39:10 +0000 (18:39 +0100)
committerSimon Brandhof <simon.brandhof@gmail.com>
Wed, 8 Feb 2012 17:52:12 +0000 (18:52 +0100)
* Major refactoring of javascript code for treemap navigation.
* Extract the execution of filters in a dedicated Ruby component : Filters.execute(filter)

24 files changed:
plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/treemap.html.erb
sonar-server/src/main/webapp/WEB-INF/app/controllers/components_controller.rb
sonar-server/src/main/webapp/WEB-INF/app/controllers/filters_controller.rb
sonar-server/src/main/webapp/WEB-INF/app/controllers/treemap_controller.rb
sonar-server/src/main/webapp/WEB-INF/app/helpers/filters_helper.rb
sonar-server/src/main/webapp/WEB-INF/app/models/filter.rb
sonar-server/src/main/webapp/WEB-INF/app/models/filter_context.rb
sonar-server/src/main/webapp/WEB-INF/app/models/filters.rb [new file with mode: 0644]
sonar-server/src/main/webapp/WEB-INF/app/models/sonar/treemap.rb
sonar-server/src/main/webapp/WEB-INF/app/views/components/_treemap_gradient.rhtml [deleted file]
sonar-server/src/main/webapp/WEB-INF/app/views/components/_treemap_set_default.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/components/_treemap_settings.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/components/index.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/dashboard/_widget.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/filters/_customize_treemap.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/filters/_tabs.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/filters/_treemap.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/filters/manage.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/filters/treemap.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/treemap/_treemap_container.html.erb
sonar-server/src/main/webapp/WEB-INF/lib/authenticated_system.rb
sonar-server/src/main/webapp/WEB-INF/lib/need_authorization.rb
sonar-server/src/main/webapp/WEB-INF/lib/treemap/node.rb
sonar-server/src/main/webapp/javascripts/application.js

index 93b2527aebf6835a8889bc54c7125fe54449dd8c..ac08223ba83ff54687eace6615b3f714d6dae373 100644 (file)
@@ -2,6 +2,7 @@
   :treemap_id => widget.id,
   :size_metric => widget_properties['sizeMetric'],
   :color_metric => widget_properties['colorMetric'],
-  :heightInPercents => widget_properties['heightInPercents'],
-  :resource_id => @resource.id
+  :height_in_percents => widget_properties['heightInPercents'],
+  :context_type => 'resource',
+  :context_id => @resource.id
   } -%>
\ No newline at end of file
index e232f8389418a5ad282ad2de3a2fe452f90d1789..30d5cab8b4747098e2635884d463c3967daf0f6c 100644 (file)
@@ -49,34 +49,11 @@ class ComponentsController < ApplicationController
     if @components_configuration.treemap_enabled? && @snapshots.size>1
       @treemap = Sonar::Treemap.new(1, default_treemap_size_metric, TREEMAP_SIZE, TREEMAP_SIZE, {
         :color_metric => default_treemap_color_metric,
-        :root_snapshot => @snapshot,
-        :browsable => false
+        :root_snapshot => @snapshot
       })
     end
   end
 
-  def treemap
-    snapshot=Snapshot.find(params[:sid])
-    not_found("Snapshot not found") unless snapshot
-    access_denied unless has_role?(:user, snapshot)
-
-    size_metric = (params[:size_metric] ? Metric.by_key(params[:size_metric]) : default_treemap_size_metric)
-    color_metric = (params[:color_metric] ? Metric.by_key(params[:color_metric]) : default_treemap_color_metric)
-
-    @treemap = Sonar::Treemap.new(1, size_metric, TREEMAP_SIZE, TREEMAP_SIZE, {
-      :color_metric => color_metric,
-      :root_snapshot => snapshot,
-      :browsable => false
-    })
-
-    render(:update) do |page|
-      page.replace_html 'treemap', @treemap.generate_html
-      page.replace_html 'treemap_gradient', :partial => 'treemap/gradient', :locals => {:metric => @treemap.color_metric}
-      page.replace_html 'treemap_set_default', :partial => 'components/treemap_set_default',
-                        :locals => {:controller => 'components', :size_metric => params[:size_metric], :color_metric => params[:color_metric], :rid => snapshot.project_id}
-    end
-  end
-
   def update_default_treemap_metrics
     Property.set(TREEMAP_SIZE_METRIC_PROPERTY, params[:size_metric])
     Property.set(TREEMAP_COLOR_METRIC_PROPERTY, params[:color_metric])
index 4e667e275a2c4a24d453007cf5d9ccf4535d7be7..8f235349921f8937d8c9be69ddce139fc914ebcc 100644 (file)
@@ -82,17 +82,15 @@ class FiltersController < ApplicationController
 
   def edit
     @filter=::Filter.find(params[:id])
-    access_denied unless editable_filter?(@filter)
+    access_denied unless @filter.authorized_to_edit?(self)
 
-    options=params
-    options[:user]=current_user
-    @filter_context=execute_filter(FilterContext.new(@filter, options))
+    @filter_context=Filters.execute(@filter, self, params)
     render :action => 'new'
   end
 
   def update
     @filter=::Filter.find(params[:id])
-    access_denied unless editable_filter?(@filter)
+    access_denied unless @filter.authorized_to_edit?(self)
 
     load_filter_from_params(@filter, params)
 
@@ -210,11 +208,12 @@ class FiltersController < ApplicationController
     column=FilterColumn.find(params[:id])
     filter=column.filter
 
-    access_denied unless editable_filter?(filter)
+    access_denied unless filter.authorized_to_edit?(self)
 
     if column.deletable?
       column.destroy
       redirect_to :action => 'edit', :id => filter.id
+      redirect_to :action => 'edit', :id => filter.id
     else
       flash[:error]='Unknown column'
       redirect_to :action => 'manage'
@@ -223,7 +222,7 @@ class FiltersController < ApplicationController
 
   def add_column
     filter=::Filter.find(params[:id])
-    access_denied unless editable_filter?(filter)
+    access_denied unless filter.authorized_to_edit?(self)
     filter.clean_columns_order() # clean the columns which are badly ordered (see SONAR-1902)
 
     fields=params[:column].split(',')
@@ -240,7 +239,7 @@ class FiltersController < ApplicationController
     column=FilterColumn.find(params[:id])
     filter=column.filter
 
-    access_denied unless editable_filter?(filter)
+    access_denied unless filter.authorized_to_edit?(self)
 
     filter.clean_columns_order() # clean the columns which are badly ordered (see SONAR-1902)
     target_column=filter.column_by_id(params[:id].to_i)
@@ -258,7 +257,7 @@ class FiltersController < ApplicationController
     column=FilterColumn.find(params[:id])
     filter=column.filter
 
-    access_denied unless editable_filter?(filter)
+    access_denied unless filter.authorized_to_edit?(self)
 
     filter.clean_columns_order() # clean the columns which are badly ordered (see SONAR-1902)
     target_column=filter.column_by_id(params[:id].to_i)
@@ -276,7 +275,7 @@ class FiltersController < ApplicationController
     column=FilterColumn.find(params[:id])
     filter=column.filter
 
-    access_denied unless editable_filter?(filter)
+    access_denied unless filter.authorized_to_edit?(self)
 
     filter.columns.each do |col|
       if col==column
@@ -297,7 +296,7 @@ class FiltersController < ApplicationController
   #---------------------------------------------------------------------
   def set_view
     filter=::Filter.find(params[:id])
-    access_denied unless editable_filter?(filter)
+    access_denied unless filter.authorized_to_edit?(self)
 
     filter.default_view=params[:view]
     filter.save
@@ -306,7 +305,7 @@ class FiltersController < ApplicationController
 
   def set_columns
     filter=::Filter.find(params[:id])
-    access_denied unless editable_filter?(filter)
+    access_denied unless filter.authorized_to_edit?(self)
 
     filter.columns.clear
     params[:columns].each do |colstring|
@@ -319,7 +318,7 @@ class FiltersController < ApplicationController
 
   def set_page_size
     filter=::Filter.find(params[:id])
-    access_denied unless editable_filter?(filter)
+    access_denied unless filter.authorized_to_edit?(self)
 
     size=[::Filter::MAX_PAGE_SIZE, params[:size].to_i].min
     size=[::Filter::MIN_PAGE_SIZE, size].max
@@ -364,7 +363,7 @@ class FiltersController < ApplicationController
   #---------------------------------------------------------------------
   def treemap
     @filter=::Filter.find(params[:id])
-    access_denied unless viewable_filter?(@filter)
+    access_denied unless @filter.authorized_to_execute?(self)
 
     @size_metric=Metric.by_key(params[:size_metric])
     @color_metric=Metric.by_key(params[:color_metric])
@@ -373,9 +372,7 @@ class FiltersController < ApplicationController
 
     @filter.sorted_column=FilterColumn.new('family' => 'metric', :kee => @size_metric.key, :sort_direction => (@size_metric.direction>=0 ? 'ASC' : 'DESC'))
 
-    options=params
-    options[:user]=current_user
-    @filter_context=execute_filter(FilterContext.new(@filter, options))
+    @filter_context=Filters.execute(@filter, self, params)
 
     @width=(params[:width]||'800').to_i
     @height=(params[:height]||'500').to_i
@@ -383,8 +380,7 @@ class FiltersController < ApplicationController
     @treemap = Sonar::Treemap.new(@filter.id, @size_metric, @width, @height, {
       :color_metric => @color_metric,
       :period_index => @filter_context.period_index,
-      :measures_by_snapshot => @filter_context.measures_by_snapshot,
-      :browsable => false
+      :measures_by_snapshot => @filter_context.measures_by_snapshot
     })
 
 
@@ -468,9 +464,7 @@ class FiltersController < ApplicationController
     if @active
       @filter=@active.filter
       unless @filter.ajax_loading?
-        options=params
-        options[:user]=current_user
-        @filter_context=execute_filter(FilterContext.new(@filter, options))
+        @filter_context=Filters.execute(@filter, self, params)
         load_masterproject() if @filter.projects_homepage?
       end
     end
index 1d12417273716494798e86244cdacc673fed323e..1406b0e2a8d7c325084331d27052630b14dfba2d 100644 (file)
@@ -39,21 +39,31 @@ class TreemapController < ApplicationController
 
     color_metric=(params[:color_metric].present? ? Metric.by_key(params[:color_metric]) : nil)
 
-    resource = Project.by_key(params[:resource])
-    bad_request('Unknown resource: ' + params[:resource]) unless resource
-    bad_request('Data not available') unless resource.last_snapshot
-    access_denied unless has_role?(:user, resource)
+    if params[:resource]
+      resource = Project.by_key(params[:resource])
+      bad_request('Unknown resource: ' + params[:resource]) unless resource
+      bad_request('Data not available') unless resource.last_snapshot
+      access_denied unless has_role?(:user, resource)
+    elsif params[:filter]
+      filter=::Filter.find(params[:filter])
+      bad_request('Unknown filter: ' + params[:filter]) unless filter
+      access_denied unless filter.authorized_to_execute?(self)
+      filter.sorted_column=FilterColumn.new('family' => 'metric', :kee => size_metric.key, :sort_direction => (size_metric.direction>=0 ? 'ASC' : 'DESC'))
+      filter_context=Filters.execute(filter, self, params)
+    else
+      bad_request('Missing parameter: resource or filter')
+    end
 
     treemap = Sonar::Treemap.new(html_id, size_metric, width.to_i, height.to_i, {
       :color_metric => color_metric,
-      :root_snapshot => resource.last_snapshot,
-      :period_index => params[:period_index].to_i,
-      :browsable => true
+      :root_snapshot => (resource ? resource.last_snapshot : nil),
+      :measures_by_snapshot => (filter_context ? filter_context.measures_by_snapshot : nil),
+      :period_index => params[:period_index].to_i
     })
 
     render :update do |page|
-      page.replace_html  "tm-#{html_id}", :partial => 'treemap', :object => treemap
-      page.replace_html  "tm-gradient-#{html_id}", :partial => 'gradient', :locals => {:metric => color_metric}
+      page.replace_html "tm-#{html_id}", :partial => 'treemap', :object => treemap
+      page.replace_html "tm-gradient-#{html_id}", :partial => 'gradient', :locals => {:metric => color_metric}
       page.hide "tm-loading-#{html_id}"
     end
   end
index 50f25552a9d8acd97f5adf410eb9b4e302967d8c..d932ec1131b0d1835d6b45b306744090a5f9344a 100644 (file)
 #
 module FiltersHelper
 
-  def execute_filter(filter_context)
-    filter=filter_context.filter
-    java_filter=Java::OrgSonarServerFilters::Filter.new
-
-    #----- FILTER ON RESOURCES
-    if filter.resource_id
-      snapshot=Snapshot.find(:first, :conditions => {:project_id => filter.resource_id, :islast => true})
-      if snapshot
-        java_filter.setPath(snapshot.root_snapshot_id, snapshot.id, snapshot.path, (snapshot.view? || snapshot.subview?))
-      else
-        java_filter.setPath(-1, -1, '', false)
-      end
-    end
-
-    if filter.favourites
-      java_filter.setFavouriteIds((filter_context.user ? filter_context.user.favourite_ids : []).to_java(:Integer))
-    end
-
-    date_criterion=filter.criterion('date')
-    if date_criterion
-      java_filter.setDateCriterion(date_criterion.operator, date_criterion.value.to_i)
-    end
-
-    key_criterion=filter.criterion('key')
-    if key_criterion
-      java_filter.setKeyRegexp(key_criterion.text_value)
-    end
-
-    name_criterion=filter.criterion('name')
-    if name_criterion
-      java_filter.setNameRegexp(name_criterion.text_value)
-    end
-
-    qualifier_criterion=filter.criterion('qualifier')
-    if qualifier_criterion
-      java_filter.setQualifiers(qualifier_criterion.text_values.to_java(:String))
-    else
-      java_filter.setQualifiers([].to_java(:String))
-    end
-
-    language_criterion=filter.criterion('language')
-    if language_criterion
-      java_filter.setLanguages(language_criterion.text_values.to_java :String)
-    end
-
-
-    #----- FILTER ON MEASURES
-    filter.measure_criteria.each do |c|
-      java_filter.createMeasureCriterionOnValue(c.metric.id, c.operator, c.value, c.variation)
-    end
-
-
-    #----- SORTED COLUMN
-    if filter_context.sorted_column_id
-      filter.sorted_column=filter_context.sorted_column_id
-    end
-    if filter.sorted_column.on_name?
-      java_filter.setSortedByName()
-
-    elsif filter.sorted_column.on_date?
-      java_filter.setSortedByDate()
-
-    elsif filter.sorted_column.on_version?
-      java_filter.setSortedByVersion()
-  
-    elsif filter.sorted_column.on_language?
-      java_filter.setSortedByLanguage()
-
-    elsif filter.sorted_column.on_metric? && filter.sorted_column.metric
-      metric=filter.sorted_column.metric
-      java_filter.setSortedMetricId(metric.id, metric.numeric?, filter.sorted_column.variation)
-
-    end
-
-
-    #----- SORTING DIRECTION
-    if filter_context.ascending_sort.nil?
-      java_filter.setAscendingSort(filter.sorted_column.ascending?)
-    else
-      filter.sorted_column.ascending=filter_context.ascending_sort
-      java_filter.setAscendingSort(filter.sorted_column.ascending?)
-    end
-
-
-    if filter_context.ascending_sort
-      filter.sorted_column.ascending=filter_context.ascending_sort
-    end
-    java_filter.setAscendingSort(filter.sorted_column.ascending?)
-
-
-    #----- VARIATION
-    java_filter.setPeriodIndex(filter_context.period_index)
-
-    #----- EXECUTION
-    java_result=java_facade.execute_filter(java_filter)
-    snapshot_ids=extract_snapshot_ids(java_result.getRows())
-
-    has_security_exclusions=(snapshot_ids.size < java_result.size())
-    filter_context.process_results(snapshot_ids, has_security_exclusions)
-  end
-
   def column_title(column, filter)
     if column.sortable?
       html=link_to h(column.display_name), url_for(:overwrite_params => {:asc => (!(column.ascending?)).to_s, :sort => column.id})
@@ -153,22 +52,6 @@ module FiltersHelper
     [size_metric, color_metric]
   end
 
-  def viewable_filter?(filter)
-    if logged_in?
-      filter.shared || (filter.user==current_user)
-    else
-      filter.shared
-    end
-  end
-
-  def editable_filter?(filter)
-    if logged_in?
-      (filter.user && filter.user==current_user) || (!filter.user && is_admin?)
-    else
-      false
-    end
-  end
-
   def period_names
     p1=Property.value('sonar.timemachine.period1', nil, 'previous_analysis')
     p2=Property.value('sonar.timemachine.period2', nil, '5')
@@ -192,26 +75,4 @@ module FiltersHelper
       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
-    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
index 6ab994cc137666cc23c1cd731f01a77bb4c99733..41eee656b8e783fabfdd52ee046ade302c910918 100644 (file)
@@ -33,7 +33,7 @@ class Filter < ActiveRecord::Base
 
   validates_length_of :name, :within => 1..100
   validates_uniqueness_of :name, :scope => :user_id, :if => Proc.new { |filter| filter.user_id }
-  validates_inclusion_of :default_view, :in => ['list','treemap'], :allow_nil => true
+  validates_inclusion_of :default_view, :in => ['list', 'treemap'], :allow_nil => true
 
   def criterion(family, key=nil)
     criteria.each do |criterion|
@@ -47,7 +47,7 @@ class Filter < ActiveRecord::Base
   def measure_criteria
     @measure_criteria ||=
       begin
-        criteria.select{|c| c.on_metric? && c.metric}
+        criteria.select { |c| c.on_metric? && c.metric }
       end
   end
 
@@ -69,19 +69,19 @@ class Filter < ActiveRecord::Base
   end
 
   def measure_columns
-    columns.select{|col| col.metric}
+    columns.select { |col| col.metric }
   end
 
   def sorted_column
     @sorted_column ||=
       begin
-        columns.to_a.find{|c| c.sort_direction} || column('name')
+        columns.to_a.find { |c| c.sort_direction } || column('name')
       end
   end
 
   def sorted_column=(col_or_id)
     if col_or_id.is_a?(Fixnum)
-      @sorted_column=columns.to_a.find{|c| c.id==col_or_id}
+      @sorted_column=columns.to_a.find { |c| c.id==col_or_id }
     else
       @sorted_column=col_or_id
     end
@@ -104,7 +104,7 @@ class Filter < ActiveRecord::Base
       TREEMAP_PAGE_SIZE
     else
       read_attribute(:page_size) || DEFAULT_PAGE_SIZE
-    end            
+    end
   end
 
   def ajax_loading?
@@ -133,14 +133,14 @@ class Filter < ActiveRecord::Base
   def period?
     period_index && period_index>0
   end
-  
+
   def column_by_id(col_id)
     columns.each do |col|
       return col if col.id==col_id
     end
     nil
   end
-    
+
   def clean_columns_order
     columns.each_with_index do |col, index|
       col.order_index=index+1
@@ -149,6 +149,18 @@ class Filter < ActiveRecord::Base
     reload
   end
 
+  def authorized_to_execute?(authenticated_system)
+    shared || (user==authenticated_system.current_user)
+  end
+
+  def authorized_to_edit?(authenticated_system)
+    if authenticated_system.logged_in?
+      (user && user==authenticated_system.current_user) || (!user && authenticated_system.is_admin?)
+    else
+      false
+    end
+  end
+
   protected
 
   def before_validation
@@ -158,7 +170,7 @@ class Filter < ActiveRecord::Base
     end
 
     # one column must be sorted
-    sorted_col=self.columns.to_a.find{|c| c.sort_direction}
+    sorted_col=self.columns.to_a.find { |c| c.sort_direction }
     unless sorted_col
       column('name').sort_direction='ASC'
     end
index 4fe3bf196d6de7c76b803b125cf21857eddf544d..b272ec46372899c6ef52f4d8b5f5e2c9c5693203 100644 (file)
@@ -18,7 +18,7 @@
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
  #
  class FilterContext
-  attr_accessor :filter, :page_size, :page_id, :security_exclusions, :period_index, :user, :sorted_column_id, :ascending_sort
+  attr_accessor :filter, :page_size, :page_id, :security_exclusions, :period_index, :sorted_column_id, :ascending_sort
 
   def initialize(filter, options={})
     @filter = filter
@@ -26,7 +26,6 @@
     @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]
     @period_index = (options[:period] ? options[:period].to_i : @filter.period_index )
     @metric_ids=(options[:metric_ids] || @filter.columns.map{|col| col.metric ? col.metric.id : nil}.compact.uniq)
   end
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/filters.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/filters.rb
new file mode 100644 (file)
index 0000000..75312ec
--- /dev/null
@@ -0,0 +1,147 @@
+#
+# Sonar, entreprise quality control 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
+#
+class Filters
+
+  def self.execute(filter, authenticated_system, options={})
+    filter_context = FilterContext.new(filter, options)
+    java_filter=Java::OrgSonarServerFilters::Filter.new
+
+    #----- FILTER ON RESOURCES
+    if filter.resource_id
+      snapshot=Snapshot.find(:first, :conditions => {:project_id => filter.resource_id, :islast => true})
+      if snapshot
+        java_filter.setPath(snapshot.root_snapshot_id, snapshot.id, snapshot.path, (snapshot.view? || snapshot.subview?))
+      else
+        java_filter.setPath(-1, -1, '', false)
+      end
+    end
+
+    if filter.favourites
+      java_filter.setFavouriteIds((authenticated_system.current_user.favourite_ids||[]).to_java(:Integer))
+    end
+
+    date_criterion=filter.criterion('date')
+    if date_criterion
+      java_filter.setDateCriterion(date_criterion.operator, date_criterion.value.to_i)
+    end
+
+    key_criterion=filter.criterion('key')
+    if key_criterion
+      java_filter.setKeyRegexp(key_criterion.text_value)
+    end
+
+    name_criterion=filter.criterion('name')
+    if name_criterion
+      java_filter.setNameRegexp(name_criterion.text_value)
+    end
+
+    qualifier_criterion=filter.criterion('qualifier')
+    if qualifier_criterion
+      java_filter.setQualifiers(qualifier_criterion.text_values.to_java(:String))
+    else
+      java_filter.setQualifiers([].to_java(:String))
+    end
+
+    language_criterion=filter.criterion('language')
+    if language_criterion
+      java_filter.setLanguages(language_criterion.text_values.to_java :String)
+    end
+
+
+    #----- FILTER ON MEASURES
+    filter.measure_criteria.each do |c|
+      java_filter.createMeasureCriterionOnValue(c.metric.id, c.operator, c.value, c.variation)
+    end
+
+
+    #----- SORTED COLUMN
+    if filter_context.sorted_column_id
+      filter.sorted_column=filter_context.sorted_column_id
+    end
+    if filter.sorted_column.on_name?
+      java_filter.setSortedByName()
+
+    elsif filter.sorted_column.on_date?
+      java_filter.setSortedByDate()
+
+    elsif filter.sorted_column.on_version?
+      java_filter.setSortedByVersion()
+
+    elsif filter.sorted_column.on_language?
+      java_filter.setSortedByLanguage()
+
+    elsif filter.sorted_column.on_metric? && filter.sorted_column.metric
+      metric=filter.sorted_column.metric
+      java_filter.setSortedMetricId(metric.id, metric.numeric?, filter.sorted_column.variation)
+
+    end
+
+
+    #----- SORTING DIRECTION
+    if filter_context.ascending_sort.nil?
+      java_filter.setAscendingSort(filter.sorted_column.ascending?)
+    else
+      filter.sorted_column.ascending=filter_context.ascending_sort
+      java_filter.setAscendingSort(filter.sorted_column.ascending?)
+    end
+
+
+    if filter_context.ascending_sort
+      filter.sorted_column.ascending=filter_context.ascending_sort
+    end
+    java_filter.setAscendingSort(filter.sorted_column.ascending?)
+
+
+    #----- VARIATION
+    java_filter.setPeriodIndex(filter_context.period_index)
+
+    #----- EXECUTION
+    java_result=Java::OrgSonarServerUi::JRubyFacade.getInstance().execute_filter(java_filter)
+    snapshot_ids=extract_snapshot_ids(java_result.getRows(), authenticated_system)
+
+    has_security_exclusions=(snapshot_ids.size < java_result.size())
+    filter_context.process_results(snapshot_ids, has_security_exclusions)
+    filter_context
+  end
+
+  private
+
+  def self.extract_snapshot_ids(sql_rows, authenticated_system)
+    sids=[]
+    project_ids=sql_rows.map { |r| r[2] ? to_integer(r[2]) : to_integer(r[1]) }.compact.uniq
+    authorized_pids=authenticated_system.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 self.to_integer(obj)
+    if obj.is_a?(Fixnum)
+      obj
+    else
+      # java.math.BigDecimal
+      obj.intValue()
+    end
+  end
+end
\ No newline at end of file
index 7571409b52be833eb29bb77a5abbd06f51d64a87..af9bf6f2bd975f93c60af835cca46417de49279a 100644 (file)
@@ -21,7 +21,7 @@ class Sonar::Treemap
   include ActionView::Helpers::UrlHelper
 
   attr_accessor :size_metric, :color_metric, :width, :height, :root_snapshot, :period_index,
-                :id, :components_size, :measures, :browsable
+                :id, :components_size, :measures
 
   def initialize(id, size_metric, width, height, options={})
     @components_size = 0
@@ -33,7 +33,6 @@ class Sonar::Treemap
     @color_metric = options[:color_metric]
     @root_snapshot = options[:root_snapshot]
     @measures_by_snapshot = options[:measures_by_snapshot] # pre-computed measures, for example by filters
-    @browsable = options[:browsable]
     if options[:period_index] && options[:period_index]>0
       @period_index = options[:period_index]
     end
@@ -62,8 +61,7 @@ class Sonar::Treemap
       o.details_at_depth = 1
     end
     html = output.to_html(root)
-    html += "<script>enableTreemap(#{@id},#{@components_size})</script>"
-    html
+    html + "<script>treemapById(#{@id}).onLoaded(#{@components_size});</script>"
   end
 
   def empty?
@@ -110,7 +108,7 @@ class Sonar::Treemap
                                   :tooltip => tooltip(resource, size_measure, color_measure),
                                   :color => html_color(color_measure),
                                   :rid => resource.copy_resource_id || resource.id,
-                                  :browsable => @browsable && resource.display_dashboard?)
+                                  :browsable => resource.display_dashboard?)
         node.add_child(child)
       end
     end
@@ -174,9 +172,11 @@ border: 1px solid #{node.color};' "
   end
 
   def draw_label(node)
-    label= "<a href='#' onclick='return openResource(#{node.rid})'>"
-    label += node_label(node)
-    label += "</a>"
-    label
+    if node.browsable
+      "<a href='#{ApplicationController.root_context}/dashboard/index/#{node.rid}'>#{node_label(node)}</a>"
+    else
+      "<a onclick=\"window.open(this.href,'resource','height=800,width=900,scrollbars=1,resizable=1');return false;\" " +
+              "href=\"#{ApplicationController.root_context}/resource/index/#{node.rid}\">#{node_label(node)}</a>"
+    end
   end
 end
\ No newline at end of file
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/components/_treemap_gradient.rhtml b/sonar-server/src/main/webapp/WEB-INF/app/views/components/_treemap_gradient.rhtml
deleted file mode 100644 (file)
index 7fbfab8..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-<%
-if color_metric && color_metric.worst_value && color_metric.best_value
-  min=0
-  max=0
-  if color_metric.worst_value<color_metric.best_value
-    min=color_metric.worst_value
-    max=color_metric.best_value
-    image = 'treemap_gradient.png'
-    id = 'treemap_gradient_direction_positive'
-  else
-    min=color_metric.best_value
-    max=color_metric.worst_value
-    image = 'treemap_gradient_inverted.png'
-    id = 'treemap_gradient_direction_negative'
-  end
-%>
-  <span class="note"><%= min -%><%= color_metric.suffix -%> <img id="<%= id -%>" src="<%= image_path image -%>" style="border: 1px solid #000; vertical-align:middle"> <%= max
-  -%><%= color_metric.suffix -%></span>
-<%
-end
-%>
\ No newline at end of file
index 9b86f8d421fe21487fc378bcf4b5b9bcd375033f..fd8e959e3cfa0f89c1aec556fcfa31eae20f1cd4 100644 (file)
@@ -1,4 +1,13 @@
-<% form_tag(
-  {:controller => controller, :action => "update_default_treemap_metrics", :size_metric => @treemap.size_metric.key, :color_metric => @treemap.color_metric.key, :rid => rid}, 
-  :id => 'form_set_default') do %>
-<% end %>
+<form method="post" id="form_set_default" name="setDefaultForm" action="<%= ApplicationController.root_context -%>/components/update_default_treemap_metrics"
+      onsubmit="">
+  <input type="hidden" name="rid" value="<%= rid -%>"/>
+  <input type="hidden" name="size_metric" />
+  <input type="hidden" name="color_metric" />
+</form>
+<script>
+  function submitDefaultForm() {
+    document.setDefaultForm.size_metric.value=$F('select_size_metric');
+    document.setDefaultForm.color_metric.value=$F('select_color_metric');
+    document.setDefaultForm.submit();
+  }
+</script>
\ No newline at end of file
index a60e814320c876ec51bac5f9a0216e885a1ea0e8..5d3a0be68eaa2a5f29dc3b1a7fa98f5a6ce28a08 100644 (file)
@@ -2,44 +2,31 @@
   <%= render :partial => 'components/treemap_set_default',
     :locals => {:controller => 'components', :size_metric => @treemap.size_metric.key, :color_metric => @treemap.color_metric.key, :rid => @project.id } %>
 </div>
-<%
-url_params = {:action => action}
-if defined?(@snapshot) && @snapshot
-  url_params[:sid]= @snapshot.id  
-end
-remote_form_for :treemap, :url => url_params, :html => { :id => 'tm_form', :method => 'get' },
-    :loading => "$('tm_form').disable();$('tm_loading').show();",
-    :complete => "$('tm_form').enable();$('tm_loading').hide();" do |form | %>
-<%= submit_tag(value = message('update_verb'), :id => 'submit_treemap', :style => 'display:none;') %>
 <table class="spaced">
 <tr>
     <td valign="bottom">
       <span class="comments"><%= message('size') -%></span>
       <br/>
       <%= select_tag 'size_metric', options_grouped_by_domain(Sonar::Treemap.size_metrics, @treemap.size_metric.key),
-        :id => 'select_size_metric', :class => 'small',:onchange => "$('submit_treemap').click();" %>
+        :id => 'select_size_metric', :class => 'small',:onchange => "return treemapById(1).changeSizeMetric(this.value);" %>
     </td>
   </tr>
   <tr>
     <td>
       <span class="comments"><%= message('color') -%></span>&nbsp;&nbsp;
-      <span id="treemap_gradient" class="comments little">
-        <%= render :partial => 'components/treemap_gradient', :locals => {:color_metric => @treemap.color_metric} %>
+      <span id="tm-gradient-1" class="comments little">
+        <%= render :partial => 'treemap/gradient', :locals => {:metric => @treemap.color_metric} %>
       </span>
-      <%= image_tag('loading.gif', {:id => "tm_loading", :style => 'display: none;'}) %>
+      <%= image_tag('loading.gif', {:id => "tm-loading-1", :style => 'display: none;'}) %>
       <br/>
       <%= select_tag 'color_metric', options_grouped_by_domain(Sonar::Treemap.color_metrics, @treemap.color_metric.key),
-          :id => 'select_color_metric', :class => 'small', :onchange => "$('submit_treemap').click();" %>
+          :id => 'select_color_metric', :class => 'small', :onchange => "return treemapById(1).changeColorMetric(this.value);" %>
     </td>
   </tr>
 
   <% if configuring? && has_role?(:admin) %>
   <tr >
-    <td class="admin"><%= button_to message('set_as_default'), "#", :id => 'set_default_treemap', :onclick => "$('form_set_default').submit()" %></td>
+    <td class="admin"><%= button_to message('set_as_default'), "#", :id => 'set_default_treemap', :onclick => "submitDefaultForm();return false;" %></td>
   </tr>
   <% end %>
 </table>
-<% end %>  
-
-
-
index be9fef2c6f3ef51ec501b7ff3aa62c8de657ef48..7bba548742720ca6a9853a0ccfb75acb80b61ccd 100644 (file)
@@ -1,75 +1,83 @@
 <% if is_admin? %>
-<div id="page-operations">
-  <ul class="operations">
+  <div id="page-operations">
+    <ul class="operations">
       <li><%= message('customize') -%>
-      <% if configuring? %>
-        <span class="green"><b><%= message('on').upcase -%></b></span> |
-        <a class="action" href="<%= url_for :overwrite_params => {:configuring => nil} -%>" id="configure-off"><%= message('off').upcase -%></a>
-      <% else %>
-        <a class="action" href="<%= url_for :overwrite_params => {:configuring => 'true'} -%>" id="configure-on"><%= message('on').upcase -%></a>
-        | <span class="red"><b><%= message('off').upcase -%></b></span>
-      <% end %>     
+        <% if configuring? %>
+          <span class="green"><b><%= message('on').upcase -%></b></span> |
+          <a class="action" href="<%= url_for :overwrite_params => {:configuring => nil} -%>" id="configure-off"><%= message('off').upcase -%></a>
+        <% else %>
+          <a class="action" href="<%= url_for :overwrite_params => {:configuring => 'true'} -%>" id="configure-on"><%= message('on').upcase -%></a>
+          | <span class="red"><b><%= message('off').upcase -%></b></span>
+        <% end %>
       </li>
-  </ul>
-</div>
+    </ul>
+  </div>
 <% end %>
 
 <% if has_role?(:admin) && configuring? %>
-  <%= render :partial => 'list_edit_mode_controls', :locals => {:configured_columns => @columns, :components_configuration => @components_configuration}%>
+  <%= render :partial => 'list_edit_mode_controls', :locals => {:configured_columns => @columns, :components_configuration => @components_configuration} %>
 <% end %>
 <% if @snapshots.empty? && @project.nil? %>
-<h3><%= message('components.no_projects_have_been_analysed') -%>No projects have been analysed.</h3>
-<p><%= message('components.explanation_launch_sonar_to_have_results') -%></p>
+  <h3><%= message('components.no_projects_have_been_analysed') -%>No projects have been analysed.</h3>
+  <p><%= message('components.explanation_launch_sonar_to_have_results') -%></p>
 <% else %>
-<table width="100%">
-  <tr>
-    <td align="left" valign="top">
-      <table id="components" class="data sortable">
-        <%= render :partial => 'list_table_header', :locals => {:configured_columns => @columns} if !configuring? || ( !is_admin? && configuring? ) %>
-        <%= render :partial => 'list_table_header_edit_mode', :locals => {:configured_columns => @columns} if configuring? && is_admin? %>
-        <tbody>
-        <% if @snapshots.empty? %>
-          <tr><td colspan="<%= @columns.size + 2 -%>">No components</td></tr>
-        <% else
-            @snapshots.each do |snapshot| %>
-            <% project = snapshot.project %>
-            <tr id="project_<%= project.id -%>">
-             <% alert_status_measure=search_measure(@measures_by_snapshot[snapshot], Metric::ALERT_STATUS)
-                alert_status_x=(alert_status_measure ? alert_status_measure.data : '')
-             %>
-              <td x="<%= alert_status_x -%>" width="1%" nowrap><%= html_measure(alert_status_measure, nil, true, nil, nil, nil) %></td>
-              <td width="1%" nowrap>
-                <% if logged_in? %><%= link_to_favourite(project) -%><% end %>
-                <%= link_to_resource(project, image_tag('zoom.png')) %>
-              </td>
-              <td class="left" x="<%= u(snapshot.project.name) -%>">
-                <%= qualifier_icon(snapshot) %>
-                <% if snapshot.project.display_dashboard? %>
-                  <a href="<%= ApplicationController.root_context + "/dashboard/index/#{snapshot.project.copy_resource_id || snapshot.project.id}" -%>"><%= snapshot.project.name -%></a>
-                <% else %>
-                  <%= snapshot.project.name %>
+  <table width="100%">
+    <tr>
+      <td align="left" valign="top">
+        <table id="components" class="data sortable">
+          <%= render :partial => 'list_table_header', :locals => {:configured_columns => @columns} if !configuring? || (!is_admin? && configuring?) %>
+          <%= render :partial => 'list_table_header_edit_mode', :locals => {:configured_columns => @columns} if configuring? && is_admin? %>
+          <tbody>
+          <% if @snapshots.empty? %>
+            <tr>
+              <td colspan="<%= @columns.size + 2 -%>">No components</td>
+            </tr>
+          <% else
+               @snapshots.each do |snapshot| %>
+              <% project = snapshot.project %>
+              <tr id="project_<%= project.id -%>">
+                <% alert_status_measure=search_measure(@measures_by_snapshot[snapshot], Metric::ALERT_STATUS)
+                   alert_status_x=(alert_status_measure ? alert_status_measure.data : '')
+                %>
+                <td x="<%= alert_status_x -%>" width="1%" nowrap><%= html_measure(alert_status_measure, nil, true, nil, nil, nil) %></td>
+                <td width="1%" nowrap>
+                  <% if logged_in? %><%= link_to_favourite(project) -%>
+                  <% end %>
+                  <%= link_to_resource(project, image_tag('zoom.png')) %>
+                </td>
+                <td class="left" x="<%= u(snapshot.project.name) -%>">
+                  <%= qualifier_icon(snapshot) %>
+                  <% if snapshot.project.display_dashboard? %>
+                    <a href="<%= ApplicationController.root_context + "/dashboard/index/#{snapshot.project.copy_resource_id || snapshot.project.id}" -%>"><%= snapshot.project.name -%></a>
+                  <% else %>
+                    <%= snapshot.project.name %>
+                  <% end %>
+                </td>
+                <% @columns.each do |column| %>
+                  <%= get_column_content(column, snapshot, @measures_by_snapshot) -%>
                 <% end %>
-              </td>
-              <% @columns.each do |column| %>
-                <%= get_column_content(column, snapshot, @measures_by_snapshot) -%>
-              <% end %>
-           </tr>
-           <% end %>
-        <% end %>
-        </tbody>
-    </table>
-    <script>TableKit.Sortable.init('components');</script>
-    <p>&nbsp;</p>
-    </td>
-    <% if @treemap %>
-      <td width="10px">&nbsp;</td>
-      <td  width="<%= @treemap.width -%>" valign="top">
-        <div id="treemap" class="treemap" style="height:<%= @treemap.height %>px">
-          <%= @treemap.generate_html() %>
-        </div>
-        <%= render :partial => 'components/treemap_settings', :locals => {:action => 'treemap'} %>
+              </tr>
+            <% end %>
+          <% end %>
+          </tbody>
+        </table>
+        <script>TableKit.Sortable.init('components');</script>
+        <p>&nbsp;</p>
       </td>
-    <% end %>
-  </tr>
-</table>
+      <% if @treemap %>
+        <td width="10px">&nbsp;</td>
+        <td width="<%= @treemap.width -%>" valign="top">
+          <script>
+            new Treemap(1, '<%= @treemap.size_metric ? @treemap.size_metric.key : '' -%>', '<%= @treemap.color_metric ? @treemap.color_metric.key : '' -%>', 100.0).init('resource',
+              <%= @project.id -%>);
+          </script>
+
+          <div id="tm-1" class="treemap" style="height:<%= @treemap.height %>px">
+            <%= @treemap.generate_html() %>
+          </div>
+          <%= render :partial => 'components/treemap_settings', :locals => {:action => 'treemap'} %>
+        </td>
+      <% end %>
+    </tr>
+  </table>
 <% end %>
index 49a370f57b12a6d71274e304552cca3e438e7f89..54e1bcc5b9152da30449855fc751d98ba41cdccb 100644 (file)
@@ -1,4 +1,4 @@
-<div class="<%= widget.key %>" style="height:100%;">
+<div style="height:100%;">
   <% if widget.configured %>
     <%
        begin
index 0b40e245251fbc7d7ea0699300790952b9c16ed8..2afa78f3d410408539ad7f3009976b40a3399206 100644 (file)
@@ -16,7 +16,6 @@
     <td>
       <%= select_tag 'columns[]', options_grouped_by_domain(Sonar::Treemap.color_metrics, color_metric.key),
         :id => 'color_metric' %>
-      <span class="comments"><%= render :partial => 'components/treemap_gradient', :locals => {:color_metric => color_metric} %></span>
     </td>
   </tr>
   <tr>
index d65702690354e7ccd465a1599300709d9cbb31cb..09fd2a9013dba94f92b01613f19e99737b29eeee 100644 (file)
@@ -2,7 +2,7 @@
 <div id="page-operations">
   <ul class="operations">
     <li><a href="<%= url_for :action => 'new' -%>" ><%= message('filters.add_filter') -%></a></li>
-    <% if @filter && @filter.id && editable_filter?(@filter) %>
+    <% if @filter && @filter.id && @filter.authorized_to_edit?(self) %>
       <li><a href="<%= url_for :action => 'edit', :id => @filter.id -%>"><%= message('filters.edit_filter') -%></a></li>
     <% end %>
     <li class="last"><%= link_to message('filters.manage_filters'), {:action => 'manage'} -%></li>
index 93d0455651d8a98db9b1802f69cc9350e45799c9..e4e23281cde0a55cf606314f7a08a52ae486aa27 100644 (file)
@@ -1,26 +1,16 @@
 <% if @filter.period? %>
-<%= message('filters.treemap_not_supported_for_period_selection') -%>
+  <%= message('filters.treemap_not_supported_for_period_selection') -%>
 
 <% else %>
   <%
-    metrics=treemap_metrics(@filter)
-    size_metric=metrics[0]
-    color_metric=metrics[1]
+     metrics=treemap_metrics(@filter)
   %>
-  <div id="treemap_loading">
-    <%= image_tag 'loading.gif' %>
-  </div>
-  <div id="treemap"> </div>
-  <script>
-  var treemap_width = $('treemap').getDimensions().width - 15;
-  var treemap_height = document.viewport.getDimensions().height - 220;
-  function load_treemap(size_metric, color_metric, hide_form) {
-    $('treemap_loading').show();
-    $('treemap').hide();
-    <%= remote_function :update => 'treemap', :url => {:action => 'treemap', :id => @filter.id},
-     :complete => "$('treemap_loading').hide();$('treemap').show();",
-     :with => "'width=' + treemap_width + '&height=' + treemap_height + '&size_metric=' + size_metric + '&color_metric=' + color_metric + '&hide_form=' + hide_form" %>
-  }
-  load_treemap('<%= size_metric.key -%>', '<%= color_metric.key -%>', <%= edit_mode -%>);
-  </script>
+  <%= render :partial => 'treemap/treemap_container', :locals => {
+    :treemap_id => @filter.id,
+    :size_metric => metrics[0],
+    :color_metric => metrics[1],
+    :height_in_percents => 50.0,
+    :context_type => 'filter',
+    :context_id => @filter.id
+  } -%>
 <% end %>
\ No newline at end of file
index 2c8b206dff142f8573c60e326328f7cc58fb81a5..8d7486cb1910dfe15afe161d1ba780e8a168baeb 100644 (file)
@@ -38,7 +38,7 @@
           <% end %>
         </td>
         <td>
-          <% if editable_filter?(active.filter) %>
+          <% if active.filter.authorized_to_edit?(self) %>
             <%= link_to message('edit'), {:action => 'edit', :id => active.filter_id}, :id => "edit-#{u active.name}"  %> |
             <%= link_to message('delete'), {:action => 'deactivate', :id => active.filter_id}, :method => :post, :confirm => message('filters.do_you_want_to_delete'), :id => "delete-#{u active.name}" %>
           <% else %>
index eabcc80f1516393c653e74d0315eb5864190bc55..9f0e385894059e3ab19b4f50be904bb09ae1c8a7 100644 (file)
 <br/>
 <% end %>
 
-<div class="treemap">
-  <%=  render :partial => 'treemap/treemap' -%>
-</div>
\ No newline at end of file
+<div>
+  <%=  render :partial => 'treemap/treemap', :locals => {:treemap => @treemap} -%>
+</div>
+<div style="margin: 5px 0 0 0" class="notes">
+  <div style="float: right"><span><%= message('treemap.click_help') -%></span></div>
+  <div id="tm-bc-<%= @filter.id -%>">/</div>
+</div>
index 008c38df8fb6bd1307045c457fdd5de8ee240dac..e313e7e4a61ff8a90168b8ae4d6db5bf31ecf6c8 100644 (file)
@@ -5,20 +5,20 @@
         <span class="comments"><%= message('size') -%></span>
         <br/>
         <%= select_tag "size", options_grouped_by_domain(Sonar::Treemap.size_metrics, (size_metric ? size_metric.key : nil), :include_empty => true),
-                       :id => "tm-size-#{treemap_id}", :class => 'small spacer-right', :onchange => "refreshTm(#{treemap_id}, null)" %>
+                       :id => "tm-size-#{treemap_id}", :class => 'small spacer-right', :onchange => "return treemapById(#{treemap_id}).changeSizeMetric(this.value)" %>
       </td>
       <td valign="top" class="thin nowrap">
         <span class="comments"><%= message('color') -%></span>
         <span id="tm-gradient-<%= treemap_id -%>" class="note"></span>
         <br/>
         <%= select_tag 'color', options_grouped_by_domain(Sonar::Treemap.color_metrics, (color_metric ? color_metric.key : nil), :include_empty => true),
-                         :id => "tm-color-#{treemap_id}", :class => 'small', :onchange => "refreshTm(#{treemap_id}, null)" %>
+                         :id => "tm-color-#{treemap_id}", :class => 'small', :onchange => "return treemapById(#{treemap_id}).changeColorMetric(this.value)" %>
         <%= image_tag 'loading.gif', :id => "tm-loading-#{treemap_id}", :style => 'vertical-align: top;display: none' -%>
       </td>
       <td></td>
     </tr>
   </table>
-  <input type="hidden" id="tm-h-<%= treemap_id -%>" value="<%= heightInPercents -%>"/>
+  <input type="hidden" id="tm-h-<%= treemap_id -%>" value="<%= height_in_percents -%>"/>
 </div>
 <div id="tm-<%= treemap_id -%>" class="spacer-bottom"></div>
 
@@ -28,9 +28,6 @@
 </div>
 
 <script>
-  treemapContexts[<%= treemap_id -%>] = [
-    [<%= resource_id -%>, '']
-  ];
-
-  refreshTm(<%= treemap_id -%>, <%= resource_id -%>);
+  new Treemap(<%= treemap_id -%>, '<%= size_metric ? size_metric.key : '' -%>', '<%= color_metric ? color_metric.key : '' -%>',
+    <%= height_in_percents -%>).init('<%= context_type -%>', <%= context_id -%>).load();
 </script>
index 10015abc17289d86b189bd9829bd53638b8048ad..d05adeae8d1940730ea82113ace602393d74da4a 100644 (file)
@@ -1,5 +1,4 @@
 module AuthenticatedSystem
-  protected
     # Returns true or false if the user is logged in.
     # Preloads @current_user with the user model if they're logged in.
     def logged_in?
index 81c967d2581f0b37667332b4177f8d222b028feb..cb6b9e77fced56ce3a8affd7f3a78f7a4d1ed1d9 100644 (file)
@@ -150,7 +150,6 @@ module NeedAuthorization
   # These methods depend on the restful_authentication plugin.
   #
   module Helper
-    protected
 
     def has_role?(role, objects=nil)
       (current_user || Anonymous.user).has_role?(role, objects)
index dbcc6e4e0fabbca30b198ed4ba87dca56d1db086..223288212d5c3d191d99d3cbeca66c5caf3ab825 100644 (file)
@@ -66,7 +66,6 @@ module Treemap
             @children = []
             @rid = opts[:rid]
             @browsable = opts[:browsable]
-
             if(@id.nil?)
                 make_id
             end
index 5cd9cea884b0fec58ba31a6080d66107f29c864d..9dcd5ecb55a95e8bdee9c7916482191905b46113 100644 (file)
@@ -140,23 +140,90 @@ var SelectBox = {
   }
 };
 
-var treemapContexts = {};
 
-function enableTreemap(treemap_id, components_size) {
-  for (var i = 1; i <= components_size; i++) {
-    var elt = $('tm-node-' + treemap_id + '-' + i);
-    elt.oncontextmenu = function () {
-      return false
-    };
-    elt.observe('mouseup', function (event) {
-      context = treemapContexts[treemap_id];
-      onTmClick(treemap_id, event, context);
-    });
-  }
+var treemaps = {};
+
+function treemapById(id) {
+  return treemaps[id];
 }
+var TreemapContext = function (type, id, label) {
+  this.type = type;
+  this.id = id;
+  this.label = label;
+};
+
+/**
+ * HTML elements :
+ * tm-#{id} : required treemap container
+ * tm-bc-#{id} : required breadcrumb
+ * tm-loading-#{id} : optional loading icon
+ */
+var Treemap = function (id, sizeMetric, colorMetric, heightInPercents) {
+  this.id = id;
+  this.sizeMetric = sizeMetric;
+  this.colorMetric = colorMetric;
+  this.heightInPercents = heightInPercents;
+  this.breadcrumb = [];
+  treemaps[id] = this;
+};
+Treemap.prototype.initResource = function (resourceId) {
+  this.breadcrumb.push(new TreemapContext('resource', resourceId, ''));
+  return this;
+};
+Treemap.prototype.initFilter = function (filterId) {
+  this.breadcrumb.push(new TreemapContext('filter', filterId, ''));
+  return this;
+};
+Treemap.prototype.init = function (type, id) {
+  this.breadcrumb.push(new TreemapContext(type, id, ''));
+  return this;
+};
+Treemap.prototype.changeSizeMetric = function (metric) {
+  this.sizeMetric = metric;
+  this.load();
+  return false;
+};
+Treemap.prototype.changeColorMetric = function (metric) {
+  this.colorMetric = metric;
+  this.load();
+  return false;
+};
+Treemap.prototype.currentContext = function () {
+  if (this.breadcrumb.length > 0) {
+    return this.breadcrumb[this.breadcrumb.length - 1];
+  }
+  return null;
+};
+Treemap.prototype.width = function () {
+  return $('tm-' + this.id).getWidth() - 10;
+};
+Treemap.prototype.load = function () {
+  var context = this.currentContext();
+  var width = this.width();
+  var height = Math.round(width * Math.abs(this.heightInPercents / 100.0));
 
+  var output = '';
+  this.breadcrumb.each(function (ctx) {
+    output += ctx.label + '&nbsp;/&nbsp;';
+  });
+  if ($('tm-bc-' + this.id)!=null) {
+  $('tm-bc-' + this.id).innerHTML = output;}
+  var loadingIcon = $('tm-loading-' + this.id);
+  if (loadingIcon != null) {
+    loadingIcon.show();
+  }
 
-function onTmClick(treemap_id, event, context) {
+  new Ajax.Request(
+    baseUrl + '/treemap/index?id=' + this.id + '&width=' + width + '&height=' + height + '&size_metric=' + this.sizeMetric + '&color_metric=' + this.colorMetric + '&' + context.type + '=' + context.id,
+    {
+      asynchronous:true,
+      evalScripts:true
+    });
+};
+Treemap.prototype.htmlNode = function (nodeId) {
+  return $('tm-node-' + this.id + '-' + nodeId);
+};
+Treemap.prototype.handleClick = function (event) {
   if (Event.isLeftClick(event)) {
     var link = event.findElement('a');
     if (link != null) {
@@ -169,44 +236,36 @@ function onTmClick(treemap_id, event, context) {
     var browsable = elt.hasAttribute('b');
     if (browsable) {
       var label = elt.innerText || elt.textContent;
-      context.push([rid, label]);
-      refreshTm(treemap_id, rid);
-    } else {
-      openResource(rid);
+      var context = new TreemapContext('resource', rid, label);
+      this.breadcrumb.push(context);
+      this.load();
     }
 
   } else if (Event.isRightClick(event)) {
-    if (context.length > 1) {
-      context.pop();
-      var rid = context[context.length - 1][0];
-      refreshTm(treemap_id, rid);
+    if (this.breadcrumb.length > 1) {
+      this.breadcrumb.pop();
+      this.load();
     }
   }
-}
-
-function refreshTm(treemap_id, resource_id) {
-  var size = $F('tm-size-' + treemap_id);
-  var color = $F('tm-color-' + treemap_id);
-  var width = $('tm-' + treemap_id).getWidth() - 10;
-  var height = Math.round(width * Math.abs(parseFloat($F('tm-h-' + treemap_id)) / 100.0));
-  var rid = (resource_id != null ? resource_id : context[context.length - 1][0]);
-
-  context = treemapContexts[treemap_id];
-  var output = '';
-  context.each(function (elt) {
-    output += elt[1] + '&nbsp;/&nbsp;';
-  });
-  $('tm-bc-' + treemap_id).innerHTML = output;
-  $('tm-loading-' + treemap_id).show();
-
-  new Ajax.Request(
-    baseUrl + '/treemap/index?id=' + treemap_id + '&width=' + width + '&height=' + height + '&size_metric=' + size + '&color_metric=' + color + '&resource=' + rid,
-    {asynchronous:true, evalScripts:true});
-
-  return false;
-}
+};
+Treemap.prototype.onLoaded = function (componentsSize) {
+  for (var i = 1; i <= componentsSize; i++) {
+    var elt = this.htmlNode(i);
+    elt.oncontextmenu = function () {
+      return false
+    };
+    elt.observe('mouseup', this.handleClick.bind(this));
+  }
+};
 
-function openResource(key) {
-  document.location = baseUrl + '/dashboard/index/' + key;
+function openResource(key, options) {
+  if (typeof popup == "undefined") {
+    popup = false;
+  }
+  if (popup) {
+    window.open(this.href, 'resource', 'height=800,width=900,scrollbars=1,resizable=1');
+  } else {
+    document.location = baseUrl + '/dashboard/index/' + key;
+  }
   return false;
 }
\ No newline at end of file