From 627602446e06bf866aa47772d2ab14eccb22584d Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Tue, 7 Feb 2012 16:23:49 +0100 Subject: [PATCH] SONAR-2069 sanitize ruby code for treemap --- .../plugins/core/widgets/TreemapWidget.java | 2 +- .../app/controllers/components_controller.rb | 63 ++++-- .../app/controllers/filters_controller.rb | 2 +- .../app/controllers/treemap_controller.rb | 2 +- .../WEB-INF/app/models/sonar/treemap.rb | 195 ++++++++++-------- .../app/models/sonar/treemap_builder.rb | 94 --------- .../webapp/WEB-INF/app/models/treemap2.rb | 170 --------------- .../components/_treemap_settings.html.erb | 4 +- .../views/filters/_customize_treemap.html.erb | 4 +- .../app/views/filters/treemap.html.erb | 4 +- .../app/views/treemap/_treemap.html.erb | 7 +- .../views/treemap/_treemap_container.html.erb | 4 +- .../src/main/webapp/WEB-INF/lib/treemap.rb | 45 ---- .../webapp/WEB-INF/lib/treemap/html_output.rb | 10 +- .../WEB-INF/lib/treemap/image_output.rb | 77 ------- .../webapp/WEB-INF/lib/treemap/svg_output.rb | 96 --------- .../main/webapp/javascripts/application.js | 25 ++- .../src/main/webapp/stylesheets/style.css | 3 - 18 files changed, 191 insertions(+), 616 deletions(-) delete mode 100644 sonar-server/src/main/webapp/WEB-INF/app/models/sonar/treemap_builder.rb delete mode 100644 sonar-server/src/main/webapp/WEB-INF/app/models/treemap2.rb delete mode 100644 sonar-server/src/main/webapp/WEB-INF/lib/treemap/image_output.rb delete mode 100644 sonar-server/src/main/webapp/WEB-INF/lib/treemap/svg_output.rb diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/TreemapWidget.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/TreemapWidget.java index b7b6640c325..733e0a07780 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/TreemapWidget.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/TreemapWidget.java @@ -39,6 +39,6 @@ public class TreemapWidget extends AbstractRubyTemplate implements RubyRailsWidg @Override protected String getTemplatePath() { - return "/org/sonar/plugins/core/widgets/treemap.html.erb"; + return "/Users/sbrandhof/projects/github/sonar/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/treemap.html.erb"; } } \ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/components_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/components_controller.rb index 100e11962b0..e232f838941 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/components_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/components_controller.rb @@ -27,6 +27,10 @@ class ComponentsController < ApplicationController TREEMAP_SIZE = 280 SECTION = Navigation::SECTION_RESOURCE + TREEMAP_DEFAULT_SIZE_METRIC = 'ncloc' + TREEMAP_SIZE_METRIC_PROPERTY = 'sonar.core.treemap.sizemetric' + TREEMAP_DEFAULT_COLOR_METRIC = 'violations_density' + TREEMAP_COLOR_METRIC_PROPERTY = 'sonar.core.treemap.colormetric' def index @components_configuration = Sonar::ComponentsConfiguration.new @@ -43,27 +47,39 @@ class ComponentsController < ApplicationController measures = component_measures(@snapshots, metrics) @measures_by_snapshot = measures_by_snapshot(@snapshots, measures) if @components_configuration.treemap_enabled? && @snapshots.size>1 - @treemap = Sonar::TreemapBuilder.build(@snapshots, TREEMAP_SIZE, TREEMAP_SIZE) + @treemap = Sonar::Treemap.new(1, default_treemap_size_metric, TREEMAP_SIZE, TREEMAP_SIZE, { + :color_metric => default_treemap_color_metric, + :root_snapshot => @snapshot, + :browsable => false + }) end end def treemap - @snapshot=Snapshot.find(params[:sid]) - @snapshots = Snapshot.find(:all, :conditions => ['parent_snapshot_id=? and qualifier<>?', @snapshot.id, Snapshot::QUALIFIER_UNIT_TEST_CLASS]) - @treemap = Sonar::TreemapBuilder.build(@snapshots, TREEMAP_SIZE, TREEMAP_SIZE, params[:size_metric], params[:color_metric]) + 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 => 'components/treemap_gradient', - :locals => {:color_metric => @treemap.color_metric} + 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} + :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(Sonar::TreemapBuilder::CONFIGURATION_DEFAULT_COLOR_METRIC, params[:color_metric]) - Property.set(Sonar::TreemapBuilder::CONFIGURATION_DEFAULT_SIZE_METRIC, params[:size_metric]) + Property.set(TREEMAP_SIZE_METRIC_PROPERTY, params[:size_metric]) + Property.set(TREEMAP_COLOR_METRIC_PROPERTY, params[:color_metric]) redirect_to :action => 'index', :id => params[:rid], :configuring => true end @@ -101,16 +117,33 @@ class ComponentsController < ApplicationController page_count.times do |page_index| page_sids=sids[page_index*page_size...(page_index+1)*page_size] measures.concat(ProjectMeasure.find(:all, :conditions => { - 'snapshot_id' => page_sids, - 'metric_id' => mids, - 'rule_id' => nil, - 'rule_priority' => nil, - 'characteristic_id' => nil, - 'committer' => nil})) + 'snapshot_id' => page_sids, + 'metric_id' => mids, + 'rule_id' => nil, + 'rule_priority' => nil, + 'characteristic_id' => nil, + 'committer' => nil})) end measures else [] end end + + def default_treemap_color_metric + metric=Metric.by_key(Property.value(TREEMAP_COLOR_METRIC_PROPERTY)) + if metric.nil? + metric = Metric.by_key(TREEMAP_DEFAULT_COLOR_METRIC) + end + metric + end + + def default_treemap_size_metric + metric=Metric.by_key(Property.value(TREEMAP_SIZE_METRIC_PROPERTY)) + if metric.nil? + metric = Metric.by_key(TREEMAP_DEFAULT_SIZE_METRIC) + end + metric + end + end \ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/filters_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/filters_controller.rb index e67bb0ce48b..4e667e275a2 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/filters_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/filters_controller.rb @@ -380,7 +380,7 @@ class FiltersController < ApplicationController @width=(params[:width]||'800').to_i @height=(params[:height]||'500').to_i - @treemap = Treemap2.new(@filter.id, @size_metric, @width, @height, { + @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, diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/treemap_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/treemap_controller.rb index 6a8151f57d8..9288782b57b 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/treemap_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/treemap_controller.rb @@ -46,7 +46,7 @@ class TreemapController < ApplicationController access_denied unless has_role?(:user, resource) end - treemap = Treemap2.new(html_id, size_metric, width.to_i, height.to_i, { + treemap = Sonar::Treemap.new(html_id, size_metric, width.to_i, height.to_i, { :color_metric => color_metric, :root_snapshot => (resource ? resource.last_snapshot : nil), :period_index => params[:period_index].to_i, diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/sonar/treemap.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/sonar/treemap.rb index afc4aba476b..6352a9a283b 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/models/sonar/treemap.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/models/sonar/treemap.rb @@ -1,92 +1,127 @@ - # - # 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 Sonar::Treemap +# +# 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 Sonar::Treemap include ActionView::Helpers::UrlHelper - - attr_accessor :color_metric, :size_metric, :width, :height - - def initialize(measures_by_snapshot, width, height, size_metric, color_metric, options={}) - @measures_by_snapshot = measures_by_snapshot + + attr_accessor :size_metric, :color_metric, :width, :height, :root_snapshot, :period_index, + :id, :components_size, :measures, :browsable + + def initialize(id, size_metric, width, height, options={}) + @components_size = 0 + @id = id @size_metric = size_metric - @color_metric = color_metric if color_metric && color_metric.treemap_color? @width = width @height = height + @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 end - + + def self.size_metrics() + Metric.all.select { |metric| + metric.treemap_size? + }.sort + end + + def self.color_metrics + Metric.all.select { |metric| + metric.treemap_color? + }.sort + end + def generate_html - root = Treemap::Node.new( :id => -1, :label => '' ) + root = Treemap::Node.new(:id => -1, :label => '') build_tree(root) - + output = Sonar::HtmlOutput.new do |o| o.width = @width o.height = @height o.full_html = false o.details_at_depth = 1 end - output.to_html(root) + html = output.to_html(root) + html += "" + html + end + + def empty? + @components_size==0 end - - + protected - def build_tree( node ) - id_counter = 0 - @measures_by_snapshot.each_pair do |snapshot, measures| - size_measure=measures[@size_metric] - color_measure=measures[@color_metric] if @color_metric + def measures_by_snapshot + @measures_by_snapshot ||= + begin + metric_ids=[@size_metric.id] + metric_ids << @color_metric.id if @color_metric && @color_metric.id!=@size_metric.id + + sql_conditions = 'snapshots.islast=? AND project_measures.characteristic_id IS NULL and project_measures.rule_id IS NULL ' + + 'and project_measures.rule_priority IS NULL and project_measures.metric_id in (?)' + sql_values = [true, metric_ids] + if @root_snapshot + sql_conditions += " AND snapshots.parent_snapshot_id=?" + sql_values << @root_snapshot.id + else + sql_conditions<<" AND snapshots.scope='PRJ' and snapshots.qualifier='TRK'" + end + hash = {} + ProjectMeasure.find(:all, :include => {:snapshot => :project}, :conditions => [sql_conditions].concat(sql_values)).each do |m| + hash[m.snapshot]||={} + hash[m.snapshot][m.metric]=m + end + hash + end + end + + def build_tree(node) + measures_by_snapshot.each_pair do |snapshot, measures| + size_measure=measures[size_metric] if size_measure + color_measure=(color_metric ? measures[color_metric] : nil) resource = snapshot.project - child = Treemap::Node.new( :id => (id_counter += 1), - :size => size_value(size_measure), - :label => resource.name(false), - :title => escape_javascript(resource.name(true)), - :tooltip => get_html_tooltip(snapshot, size_measure, color_measure), - :color => html_color(color_measure), - :url => get_url(snapshot)) + child = Treemap::Node.new(:id => "#{@id}-#{@components_size += 1}", + :size => size_value(size_measure), + :label => resource.name(false), + :title => escape_javascript(resource.name(true)), + :tooltip => tooltip(resource, size_measure, color_measure), + :color => html_color(color_measure), + :rid => resource.copy_resource_id || resource.id, + :browsable => @browsable && resource.display_dashboard?) node.add_child(child) end end - end - - - def get_url(snapshot) - if snapshot.display_dashboard? - "document.location='#{ApplicationController.root_context}/dashboard/index/#{snapshot.project.copy_resource_id || snapshot.project_id}'" - else - color_metric_key=(@color_metric ? @color_metric.key : nil) - "window.open('#{ApplicationController.root_context}/resource/index/#{snapshot.project_id}?metric=#{color_metric_key}','resource','height=800,width=900,scrollbars=1,resizable=1');return false;" - end end - - def get_html_tooltip(snapshot, size_measure, color_measure) - html = "" - html += "" + + def tooltip(resource, size_measure, color_measure) + html=CGI::escapeHTML(resource.name(true)) + html += " - #{CGI::escapeHTML(@size_metric.short_name)}: #{CGI::escapeHTML(size_measure.formatted_value)}" if color_measure - html += "" + html += " - #{CGI::escapeHTML(@color_metric.short_name)}: #{CGI::escapeHTML(color_measure.formatted_value)}" end - html += "
#{escape_javascript(@size_metric.short_name)}#{escape_javascript(size_measure ? size_measure.formatted_value : '-')}
#{escape_javascript(@color_metric.short_name)}#{escape_javascript(color_measure ? color_measure.formatted_value : '-')}
" html end @@ -100,7 +135,7 @@ class Sonar::Treemap 0.0 end end - + def html_color(measure) MeasureColor.color(measure).html end @@ -108,42 +143,40 @@ class Sonar::Treemap end class Sonar::HtmlOutput < Treemap::HtmlOutput - attr_accessor(:link_url) - + def draw_node(node) return "" if node.bounds.nil? - html = "" + html = '' html += "
" - html += "" + html + '
' end - - def draw_tooltips(node) - html='' - html + + def draw_label(node) + label= "" + label += node_label(node) + label += "" + label end end \ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/sonar/treemap_builder.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/sonar/treemap_builder.rb deleted file mode 100644 index 6ec0a08b225..00000000000 --- a/sonar-server/src/main/webapp/WEB-INF/app/models/sonar/treemap_builder.rb +++ /dev/null @@ -1,94 +0,0 @@ - # - # 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 Sonar::TreemapBuilder - DEFAULT_WIDTH = 280 - DEFAULT_HEIGHT = 280 - - CONFIGURATION_DEFAULT_COLOR_METRIC = 'sonar.core.treemap.colormetric' - CONFIGURATION_DEFAULT_SIZE_METRIC = 'sonar.core.treemap.sizemetric' - - def self.size_metrics(options={}) - Metric.all.select{ |metric| - metric.treemap_size? - }.sort - end - - def self.color_metrics - Metric.all.select{ |metric| - metric.treemap_color? - }.sort - end - - def self.build(snapshots, width=DEFAULT_WIDTH, height=DEFAULT_HEIGHT, size_metric_key=nil, color_metric_key=nil) - size_metric = Metric.by_key(size_metric_key) || default_size_metric - color_metric = Metric.by_key(color_metric_key) || default_color_metric - - if snapshots.empty? - measures = [] - else - # temporary fix for SONAR-1098 - snapshots=snapshots[0...999] - measures = ProjectMeasure.find(:all, - :conditions => ['committer IS NULL and characteristic_id IS NULL and rule_id IS NULL and rule_priority IS NULL and metric_id IN (?) and snapshot_id IN (?)', - [size_metric.id, color_metric.id], snapshots.map{|s| s.id}]) - end - Sonar::Treemap.new(measures_hash_by_snapshot(snapshots, measures), width, height, size_metric, color_metric) - end - - private - - def self.default_color_metric - metric=Metric.by_key(Property.value(CONFIGURATION_DEFAULT_COLOR_METRIC)) - if metric.nil? - metric = Metric.by_key(Metric::VIOLATIONS_DENSITY) - end - metric - end - - def self.default_size_metric - metric=Metric.by_key(Property.value(CONFIGURATION_DEFAULT_SIZE_METRIC)) - if metric.nil? - metric = Metric.by_key(Metric::NCLOC) - end - metric - end - - def self.measures_hash_by_snapshot(snapshots, measures) - snapshot_by_id = {} - snapshots.each {|s| snapshot_by_id[s.id]=s} - hash={} - measures.each do |m| - hash[snapshot_by_id[m.snapshot_id]] ||= {} - hash[snapshot_by_id[m.snapshot_id]][m.metric]=m - end - hash - end - - def self.measures_by_snapshot(snapshots, measures) - snapshot_by_id = {} - snapshots.each {|s| snapshot_by_id[s.id]=s} - hash={} - measures.each do |m| - hash[snapshot_by_id[m.snapshot_id]] ||= [] - hash[snapshot_by_id[m.snapshot_id]] << m - end - hash - end -end \ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/treemap2.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/treemap2.rb deleted file mode 100644 index abf87c48569..00000000000 --- a/sonar-server/src/main/webapp/WEB-INF/app/models/treemap2.rb +++ /dev/null @@ -1,170 +0,0 @@ -# -# 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 Treemap2 - include ActionView::Helpers::UrlHelper - - attr_accessor :size_metric, :color_metric, :width, :height, :root_snapshot, :period_index, - :id, :id_counter, :measures, :browsable - - def initialize(id, size_metric, width, height, options={}) - @id_counter = 0 - @id = id - @size_metric = size_metric - @width = width - @height = height - - @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 - end - - def generate_html - root = Treemap::Node.new(:id => -1, :label => '') - build_tree(root) - - output = Sonar::HtmlOutput.new do |o| - o.width = @width - o.height = @height - o.full_html = false - o.details_at_depth = 1 - end - output.to_html(root) - end - - def empty? - @id_counter==0 - end - - protected - - def measures_by_snapshot - @measures_by_snapshot ||= - begin - metric_ids=[@size_metric.id] - metric_ids << @color_metric.id if @color_metric && @color_metric.id!=@size_metric.id - - sql_conditions = 'snapshots.islast=? AND project_measures.characteristic_id IS NULL and project_measures.rule_id IS NULL ' + - 'and project_measures.rule_priority IS NULL and project_measures.metric_id in (?)' - sql_values = [true, metric_ids] - if @root_snapshot - sql_conditions += " AND snapshots.parent_snapshot_id=?" - sql_values << @root_snapshot.id - else - sql_conditions<<" AND snapshots.scope='PRJ' and snapshots.qualifier='TRK'" - end - - hash = {} - ProjectMeasure.find(:all, :include => {:snapshot => :project}, :conditions => [sql_conditions].concat(sql_values)).each do |m| - hash[m.snapshot]||={} - hash[m.snapshot][m.metric]=m - end - hash - end - end - - def build_tree(node) - measures_by_snapshot.each_pair do |snapshot, measures| - size_measure=measures[size_metric] - color_measure=(color_metric ? measures[color_metric] : nil) - resource = snapshot.project - child = Treemap::Node.new(:id => "#{@id}-#{@id_counter += 1}", - :size => size_value(size_measure), - :label => resource.name(false), - :title => escape_javascript(resource.name(true)), - :tooltip => tooltip(resource, size_measure, color_measure), - :color => html_color(color_measure), - :rid => resource.copy_resource_id || resource.id, - :browsable => @browsable && resource.display_dashboard?) - node.add_child(child) - end - end - - def tooltip(resource, size_measure, color_measure) - html=CGI::escapeHTML(resource.name(true)) - html += " - #{CGI::escapeHTML(@size_metric.short_name)}: #{CGI::escapeHTML(size_measure.formatted_value)}" - if color_measure - html += " - #{CGI::escapeHTML(@color_metric.short_name)}: #{CGI::escapeHTML(color_measure.formatted_value)}" - end - html - end - - def size_value(measure) - if @period_index - var=measure.variation(@period_index) - var ? var.to_f.abs : 0.0 - elsif measure.value - measure.value.to_f.abs||0.0 - else - 0.0 - end - end - - def html_color(measure) - MeasureColor.color(measure).html - end - -end - -class Sonar::HtmlOutput < Treemap::HtmlOutput - - def draw_node(node) - return "" if node.bounds.nil? - - html = '' - html += "
" - html += "
0) - node.children.each do |c| - html += draw_node(c) - end - end - html += "
" - end - - def draw_label(node) - label= "" - label += node_label(node) - label += "" - label - end - - def draw_tooltips(node) - '' - end -end \ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/components/_treemap_settings.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/components/_treemap_settings.html.erb index 13d15a14429..a60e814320c 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/components/_treemap_settings.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/components/_treemap_settings.html.erb @@ -16,7 +16,7 @@ remote_form_for :treemap, :url => url_params, :html => { :id => 'tm_form', :meth <%= message('size') -%>
- <%= select_tag 'size_metric', options_grouped_by_domain(Sonar::TreemapBuilder.size_metrics, @treemap.size_metric.key), + <%= 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();" %> @@ -28,7 +28,7 @@ remote_form_for :treemap, :url => url_params, :html => { :id => 'tm_form', :meth <%= image_tag('loading.gif', {:id => "tm_loading", :style => 'display: none;'}) %>
- <%= select_tag 'color_metric', options_grouped_by_domain(Sonar::TreemapBuilder.color_metrics, @treemap.color_metric.key), + <%= 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();" %> diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/filters/_customize_treemap.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/filters/_customize_treemap.html.erb index dacce6494f5..0b40e245251 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/filters/_customize_treemap.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/filters/_customize_treemap.html.erb @@ -7,14 +7,14 @@ <%= message('size') -%>: - <%= select_tag 'columns[]', options_grouped_by_domain(Sonar::TreemapBuilder.size_metrics(), size_metric.key), + <%= select_tag 'columns[]', options_grouped_by_domain(Sonar::Treemap.size_metrics(), size_metric.key), :id => 'size_metric' %> <%= message('color') -%>: - <%= select_tag 'columns[]', options_grouped_by_domain(Sonar::TreemapBuilder.color_metrics, color_metric.key), + <%= select_tag 'columns[]', options_grouped_by_domain(Sonar::Treemap.color_metrics, color_metric.key), :id => 'color_metric' %> <%= render :partial => 'components/treemap_gradient', :locals => {:color_metric => color_metric} %> diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/filters/treemap.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/filters/treemap.html.erb index 9dc29b9844a..eabcc80f151 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/filters/treemap.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/filters/treemap.html.erb @@ -4,14 +4,14 @@ <%= message('size') -%>:
- <%= select_tag 'size_metric', options_grouped_by_domain(Sonar::TreemapBuilder.size_metrics(), @size_metric.key), + <%= select_tag 'size_metric', options_grouped_by_domain(Sonar::Treemap.size_metrics(), @size_metric.key), :id => 'size_metric', :class => 'small', :onchange => "load_treemap(this.form.size_metric.value,this.form.color_metric.value, false);return false;" %> <%= message('color') -%>: <%= render :partial => 'treemap/gradient', :locals => {:metric => @color_metric} %>
- <%= select_tag 'color_metric', options_grouped_by_domain(Sonar::TreemapBuilder.color_metrics, @color_metric.key), + <%= select_tag 'color_metric', options_grouped_by_domain(Sonar::Treemap.color_metrics, @color_metric.key), :id => 'color_metric', :class => 'small', :onchange => "load_treemap(this.form.size_metric.value,this.form.color_metric.value, false);return false;" %> diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/treemap/_treemap.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/treemap/_treemap.html.erb index d82c2b92b87..e416740a27e 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/treemap/_treemap.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/treemap/_treemap.html.erb @@ -1,8 +1,3 @@
<%= treemap.generate_html() -%> -
- + \ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/treemap/_treemap_container.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/treemap/_treemap_container.html.erb index 211bc5981c4..0fcad775c8b 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/treemap/_treemap_container.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/treemap/_treemap_container.html.erb @@ -4,14 +4,14 @@ <%= message('size') -%>
- <%= select_tag "size", options_grouped_by_domain(Sonar::TreemapBuilder.size_metrics, (size_metric ? size_metric.key : nil), :include_empty => true), + <%= 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)" %> <%= message('color') -%>
- <%= select_tag 'color', options_grouped_by_domain(Sonar::TreemapBuilder.color_metrics, (color_metric ? color_metric.key : nil), :include_empty => true), + <%= 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)" %> <%= image_tag 'loading.gif', :id => "tm-loading-#{treemap_id}", :style => 'vertical-align: top;display: none' -%> diff --git a/sonar-server/src/main/webapp/WEB-INF/lib/treemap.rb b/sonar-server/src/main/webapp/WEB-INF/lib/treemap.rb index c2888c49547..cd96e3fe436 100644 --- a/sonar-server/src/main/webapp/WEB-INF/lib/treemap.rb +++ b/sonar-server/src/main/webapp/WEB-INF/lib/treemap.rb @@ -19,48 +19,3 @@ require File.dirname(__FILE__) + '/treemap/squarified_layout' require File.dirname(__FILE__) + '/treemap/html_output' require File.dirname(__FILE__) + '/treemap/rectangle' require File.dirname(__FILE__) + '/treemap/gradient_color' - -# XXX these are still expirmental. Requires RMagick -# require File.dirname(__FILE__) + '/treemap/image_output' -# require File.dirname(__FILE__) + '/treemap/svg_output' - -module Treemap - VERSION = "0.0.1" - - def Treemap::dump_tree(node) - puts "#{node.label}: #{node.bounds.to_s}" - node.children.each do |c| - dump_tree(c) - end - end - - def Treemap::tree_from_xml(file) - doc = REXML::Document.new(file) - node_from_xml(doc.root) - end - - def Treemap::node_from_xml(xmlnode) - node = Treemap::Node.new - - node.label = xmlnode.attributes["label"] - id = xmlnode.attributes["id"] - if(!id.nil?) - node.id = id.to_s - end - - node.size = xmlnode.attributes["size"] - node.size = node.size.to_f unless node.size.nil? - - node.color = xmlnode.attributes["change"] - node.color = node.color.to_f unless node.color.nil? - - - xmlnode.elements.each do |c| - child = node_from_xml(c) - node.add_child(child) if !child.nil? - end - - return nil if node.size < 5 - node - end -end diff --git a/sonar-server/src/main/webapp/WEB-INF/lib/treemap/html_output.rb b/sonar-server/src/main/webapp/WEB-INF/lib/treemap/html_output.rb index dac5eddcfa8..63873cc69a6 100644 --- a/sonar-server/src/main/webapp/WEB-INF/lib/treemap/html_output.rb +++ b/sonar-server/src/main/webapp/WEB-INF/lib/treemap/html_output.rb @@ -91,8 +91,7 @@ CSS end html += draw_node(node) - html += draw_tooltips(node) - + if(@full_html) html += "" end @@ -132,10 +131,7 @@ CSS end end - html += "" - end - - def draw_tooltips(node) - '' + html + '' end + end diff --git a/sonar-server/src/main/webapp/WEB-INF/lib/treemap/image_output.rb b/sonar-server/src/main/webapp/WEB-INF/lib/treemap/image_output.rb deleted file mode 100644 index f6cbeddc092..00000000000 --- a/sonar-server/src/main/webapp/WEB-INF/lib/treemap/image_output.rb +++ /dev/null @@ -1,77 +0,0 @@ -# -# image_output.rb - RubyTreemap -# -# Copyright (c) 2006 by Andrew Bruno -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# - -require 'RMagick' -require File.dirname(__FILE__) + "/output_base" - -class Treemap::ImageOutput < Treemap::OutputBase - def initialize - super - - # default options for ImageOutput - - yield self if block_given? - end - - def setup_draw - draw = Magick::Draw.new - draw.stroke_width(1) - draw.stroke("#000000") - draw.stroke_opacity(1) - draw.fill_opacity(1) - draw.font_family = "Verdana" - draw.pointsize = 12 - draw.gravity = Magick::WestGravity - - return draw - end - - def new_image - Magick::Image.new(@width, @height) {self.background_color = "white"} - end - - def to_png(node, filename="treemap.png") - # - # XXX Need to flesh out this method. Add in label drawing. - # - - image = self.new_image - draw = self.setup_draw - - @bounds = self.bounds - - # Pad for root border - @bounds.x2 -= 1 - @bounds.y2 -= 1 - - @layout.process(node, @bounds) - - draw_map(node, draw, image) - - # render image - draw.draw(image) - image.write(filename) - end - - def draw_map(node, draw, image) - return "" if node.nil? - if(node.color.nil?) - draw.fill("#CCCCCC") - else - draw.fill("#" + @color.get_hex_color(node.color)) - end - draw.rectangle(node.bounds.x1, node.bounds.y1, node.bounds.x2, node.bounds.y2) - node.children.each do |c| - draw_map(c, draw, image) - end - end -end diff --git a/sonar-server/src/main/webapp/WEB-INF/lib/treemap/svg_output.rb b/sonar-server/src/main/webapp/WEB-INF/lib/treemap/svg_output.rb deleted file mode 100644 index 864d8089911..00000000000 --- a/sonar-server/src/main/webapp/WEB-INF/lib/treemap/svg_output.rb +++ /dev/null @@ -1,96 +0,0 @@ -# -# svg_output.rb - RubyTreemap -# -# Copyright (c) 2006 by Andrew Bruno -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# - -require 'cgi' -require 'RMagick' - -require File.dirname(__FILE__) + "/output_base" - -class Treemap::SvgOutput < Treemap::OutputBase - - def initialize - super - - yield self if block_given? - end - - def node_label(node) - CGI.escapeHTML(node.label) - end - - def node_color(node) - color = "#CCCCCC" - - if(!node.color.nil?) - if(not Numeric === node.color) - color = node.color - else - color = "#" + @color.get_hex_color(node.color) - end - end - - color - end - - def to_png(node, filename="treemap.png") - svg = to_svg(node) - img = Magick::Image.from_blob(svg) { self.format = "SVG" } - img[0].write(filename) - end - - def to_svg(node) - bounds = self.bounds - - @layout.process(node, bounds) - - draw_map(node) - end - - def draw_map(node) - svg = "" - - svg += draw_node(node) - svg += "" - svg - end - - def draw_node(node) - return "" if node.bounds.nil? - - svg = "" - svg += " 0) - node.children.each do |c| - svg += draw_node(c) - end - end - - svg - end -end diff --git a/sonar-server/src/main/webapp/javascripts/application.js b/sonar-server/src/main/webapp/javascripts/application.js index c79ebabffaa..5cd9cea884b 100644 --- a/sonar-server/src/main/webapp/javascripts/application.js +++ b/sonar-server/src/main/webapp/javascripts/application.js @@ -142,17 +142,20 @@ var SelectBox = { var treemapContexts = {}; -function addTmEvent(treemap_id, elt_index) { - var elt = $('tm-node-' + treemap_id + '-' + elt_index); - elt.oncontextmenu = function () { - return false - }; - elt.observe('mouseup', function (event) { - context = treemapContexts[treemap_id]; - onTmClick(treemap_id, event, context); - }); +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); + }); + } } + function onTmClick(treemap_id, event, context) { if (Event.isLeftClick(event)) { var link = event.findElement('a'); @@ -185,8 +188,8 @@ 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 * parseFloat($F('tm-h-' + treemap_id) / 100.0)); - var rid = (resource_id!=null ? resource_id : context[context.length-1][0]); + 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 = ''; diff --git a/sonar-server/src/main/webapp/stylesheets/style.css b/sonar-server/src/main/webapp/stylesheets/style.css index afc4f151da1..24104be5c8e 100644 --- a/sonar-server/src/main/webapp/stylesheets/style.css +++ b/sonar-server/src/main/webapp/stylesheets/style.css @@ -517,9 +517,6 @@ h4, .h4 { position: relative; cursor: pointer; } -.treemap .label { - color: #fff; -} .treemap a { color: #FFF; text-decoration: none; -- 2.39.5