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