diff options
Diffstat (limited to 'sonar-server/src/main/webapp/WEB-INF/app/models/sonar')
-rw-r--r-- | sonar-server/src/main/webapp/WEB-INF/app/models/sonar/treemap.rb | 195 | ||||
-rw-r--r-- | sonar-server/src/main/webapp/WEB-INF/app/models/sonar/treemap_builder.rb | 94 |
2 files changed, 114 insertions, 175 deletions
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 += "<script>enableTreemap(#{@id},#{@components_size})</script>" + 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 = "<table>" - html += "<tr><td align=left>#{escape_javascript(@size_metric.short_name)}</td><td align=right><b>#{escape_javascript(size_measure ? size_measure.formatted_value : '-')}</b></td></tr>" + + 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 += "<tr><td align=left>#{escape_javascript(@color_metric.short_name)}</td><td align=right><b>#{escape_javascript(color_measure ? color_measure.formatted_value : '-')}</b></td></tr>" + html += " - #{CGI::escapeHTML(@color_metric.short_name)}: #{CGI::escapeHTML(color_measure.formatted_value)}" end - html += "</table>" 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 += "<div id=\"node-#{node.id}\" style=\"" html += "overflow:hidden;position:absolute;" html += "left:#{node.bounds.x1}px; top:#{node.bounds.y1}px;" html += "width:#{node.bounds.width}px;height: #{node.bounds.height}px;" html += "background-color:#FFF;" - html += "\" class=\"node\">" - html += "<div id=\"link_node-#{node.id}\" style='margin: 2px;background-color: #{node.color}; height: #{node.bounds.height-4}px; border: 1px solid #{node.color};' " - if node.url && @details_at_depth==node.depth - html += "onClick=\"#{node.url}\" onmouseover=\"this.style.borderColor='#111';\" onmouseout=\"this.style.borderColor='#{node.color}';\"" + html += "\" alt='#{node.tooltip}' title='#{node.tooltip}'>" + html += "<div rid='#{node.rid}' id=\"tm-node-#{node.id}\" style='margin: 1px;background-color: #{node.color}; height: #{node.bounds.height-4}px; +border: 1px solid #{node.color};' " + if node.browsable + html += "b=1 " + end + if @details_at_depth==node.depth + html += "onmouseover=\"this.style.borderColor='#444';\" onmouseout=\"this.style.borderColor='#{node.color}';\"" end html += ' >' html += draw_node_body(node) - if(!node.children.nil? && node.children.size > 0) + if (!node.children.nil? && node.children.size > 0) node.children.each do |c| html += draw_node(c) end end - html += "</div></div>" + html + '</div></div>' end - - def draw_tooltips(node) - html='<script type="text/javascript">' - - node.children.each do |c| - if @details_at_depth==c.depth - html += "new Tip($('node-#{c.id.to_s}'), '#{c.tooltip}', {title: '#{c.title}'});" - end - end - html += '</script>' - html + + def draw_label(node) + label= "<a href='#' onclick='return openResource(#{node.rid})'>" + label += node_label(node) + label += "</a>" + 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 |