Browse Source

SONAR-7780 Apply feedback

tags/6.0-RC1
Simon Brandhof 8 years ago
parent
commit
5112fc0bc1
25 changed files with 148 additions and 250 deletions
  1. 1
    1
      it/it-tests/src/test/resources/measureHistory/HistoryUiTest/history-timeline-widget/should-display-even-if-one-missing-metric.html
  2. 16
    19
      server/sonar-server/src/main/resources/org/sonar/server/dashboard/widget/time_machine.html.erb
  3. 26
    26
      server/sonar-server/src/main/resources/org/sonar/server/dashboard/widget/timeline.html.erb
  4. 0
    4
      server/sonar-server/src/test/java/org/sonar/server/measure/MeasureFilterExecutorTest.java
  5. 1
    1
      server/sonar-web/src/main/webapp/WEB-INF/app/controllers/api/events_controller.rb
  6. 49
    49
      server/sonar-web/src/main/webapp/WEB-INF/app/controllers/api/resources_controller.rb
  7. 3
    3
      server/sonar-web/src/main/webapp/WEB-INF/app/controllers/comparison_controller.rb
  8. 1
    1
      server/sonar-web/src/main/webapp/WEB-INF/app/controllers/project_controller.rb
  9. 0
    28
      server/sonar-web/src/main/webapp/WEB-INF/app/models/chart_measure.rb
  10. 0
    22
      server/sonar-web/src/main/webapp/WEB-INF/app/models/loaded_template.rb
  11. 1
    1
      server/sonar-web/src/main/webapp/WEB-INF/app/models/measure_filter.rb
  12. 5
    31
      server/sonar-web/src/main/webapp/WEB-INF/app/models/project.rb
  13. 3
    26
      server/sonar-web/src/main/webapp/WEB-INF/app/models/snapshot.rb
  14. 13
    10
      server/sonar-web/src/main/webapp/WEB-INF/app/models/sonar/timemachine_row.rb
  15. 5
    5
      server/sonar-web/src/main/webapp/WEB-INF/app/models/trends_chart.rb
  16. 2
    2
      server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_nolayout.html.erb
  17. 1
    1
      server/sonar-web/src/main/webapp/WEB-INF/app/views/project/deletion.html.erb
  18. 1
    1
      server/sonar-web/src/main/webapp/WEB-INF/app/views/project/history.html.erb
  19. 2
    2
      server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1255_fix_project_uuid_of_developer_projects.rb
  20. 4
    3
      sonar-db/src/main/java/org/sonar/db/measure/MeasureQuery.java
  21. 3
    3
      sonar-db/src/main/java/org/sonar/db/measure/PastMeasureDto.java
  22. 2
    2
      sonar-db/src/main/java/org/sonar/db/version/MigrationStepModule.java
  23. 6
    6
      sonar-db/src/main/java/org/sonar/db/version/v60/FixProjectUuidOfDeveloperProjects.java
  24. 3
    3
      sonar-db/src/test/java/org/sonar/db/version/v60/FixProjectUuidOfDeveloperProjectsTest.java
  25. 0
    0
      sonar-db/src/test/resources/org/sonar/db/version/v60/FixProjectUuidOfDeveloperProjectsTest/in_progress_projects.sql

+ 1
- 1
it/it-tests/src/test/resources/measureHistory/HistoryUiTest/history-timeline-widget/should-display-even-if-one-missing-metric.html View File

@@ -16,7 +16,7 @@
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>waitForElementPresent</td>
<td>timeline-chart-1</td>
<td></td>
</tr>

+ 16
- 19
server/sonar-server/src/main/resources/org/sonar/server/dashboard/widget/time_machine.html.erb View File

@@ -8,7 +8,7 @@
if metric
metric_ids << metric.id
row=Sonar::TimemachineRow.new(metric)
rows_by_metric_id[metric.id]=row
rows_by_metric_id[metric.id] = row
end
end
if metric_ids.empty?
@@ -24,29 +24,26 @@
if from_date
options[:from] = from_date
end
snapshots=Snapshot.for_timemachine_widget(@resource, number_of_columns, options)
sids = snapshots.collect { |s| s.id }.uniq
measures=ProjectMeasure.find(:all,
analyses = Snapshot.for_timemachine_widget(@resource, number_of_columns, options)
analysis_uuids = analyses.collect { |a| a.uuid }.uniq
measures = ProjectMeasure.find(:all,
:conditions =>
["snapshot_id IN (:snapshot_id) AND metric_id IN (:metric_id) AND person_id IS NULL",
{:snapshot_id => sids, :metric_id => metric_ids}
["analysis_uuid IN (:analysis_uuids) AND component_uuid = :component_uuid and metric_id IN (:metric_id) AND person_id IS NULL",
{:analysis_uuids => analysis_uuids, :component_uuid => @resource.uuid, :metric_id => metric_ids}
]
)


# Prepare the rows to display
snapshot_by_id={}
snapshots.each do |s|
snapshot_by_id[s.id]=s
analyses_by_uuid = {}
analyses.each do |a|
analyses_by_uuid[a.uuid] = a
end
measures.each do |measure|
next unless measure.metric

if measure.metric.timemachine? && (measure.value || measure.text_value)
row=rows_by_metric_id[measure.metric_id]

#optimization : avoid eager loading of snapshots
measure.snapshot=snapshot_by_id[measure.snapshot_id]
row = rows_by_metric_id[measure.metric_id]
row.add_measure(measure)
end
end
@@ -64,7 +61,7 @@
sparklines_by_row = {}
if widget_properties["displaySparkLine"]
rows.each do |row|
sparkline = row.sparkline
sparkline = row.sparkline(analyses)
sparklines_by_row[row] = sparkline if sparkline
end
end
@@ -84,11 +81,11 @@
<tr>
<th></th>
<%
snapshots.each do |snapshot|
event = snapshot.event('Version')
analyses.each do |analysis|
event = analysis.event('Version')
%>
<th nowrap="nowrap" style="vertical-align:top;text-align: right;font-size: 10px">
<%= l snapshot.created_at.to_date -%>
<%= l analysis.created_at.to_date -%>
<br/>
<%= event.name unless event==nil -%>
</th>
@@ -108,8 +105,8 @@
<%= row.metric.short_name %>
</td>
<%
snapshots.each do |snapshot|
measure=row.measure(snapshot)
analyses.each do |analysis|
measure = row.measure(analysis)
%>
<td width="1%" nowrap="nowrap" class="right"><%= format_measure(measure, :skip_span_id => true) %></td>
<% end %>

+ 26
- 26
server/sonar-server/src/main/resources/org/sonar/server/dashboard/widget/timeline.html.erb View File

@@ -32,45 +32,45 @@
options[:from] = from_date
end
# Variables used if undefinedToZero is set to true
previous_snapshot_id = nil
previous_analysis_uuid = nil
previous_created_at = nil
first_trend_item = true
metric_previous_snapshot_id = {}
metric_count_per_snapshot_id = {}
metric_previous_analysis_uuid = {}
metric_count_per_analysis_uuid = {}
total_number_of_metrics = metric_map.keys.size()
TrendsChart.time_machine_measures(@resource, metric_data_map.keys, options).each() do |trend_item|
sid = trend_item["sid"]
analysis_uuid = trend_item["analysis_uuid"]
if undefinedToZero
if first_trend_item
first_trend_item = false
previous_snapshot_id = sid
previous_analysis_uuid = analysis_uuid
previous_created_at = Time.at(trend_item["created_at"].to_i/1000)
end
if previous_snapshot_id != sid
if metric_count_per_snapshot_id[previous_snapshot_id] != total_number_of_metrics
if previous_analysis_uuid != analysis_uuid
if metric_count_per_analysis_uuid[previous_analysis_uuid] != total_number_of_metrics
metric_map.keys.each do |metric_id|
unless metric_previous_snapshot_id.include?(metric_id)
metric_data_map[metric_id] << {:date => previous_created_at, :value => 0.00, :sid => previous_snapshot_id}
if metric_count_per_snapshot_id[previous_snapshot_id]
metric_count_per_snapshot_id[previous_snapshot_id] += 1
unless metric_previous_analysis_uuid.include?(metric_id)
metric_data_map[metric_id] << {:date => previous_created_at, :value => 0.00, :analysis_uuid => previous_analysis_uuid}
if metric_count_per_analysis_uuid[previous_analysis_uuid]
metric_count_per_analysis_uuid[previous_analysis_uuid] += 1
else
metric_count_per_snapshot_id[previous_snapshot_id] = 1
metric_count_per_analysis_uuid[previous_analysis_uuid] = 1
end
end
end
end
previous_snapshot_id = sid
previous_analysis_uuid = analysis_uuid
previous_created_at = Time.at(trend_item["created_at"].to_i/1000)
metric_previous_snapshot_id = {}
metric_previous_analysis_uuid = {}
end
metric_previous_snapshot_id[trend_item["metric_id"].to_i] = 1
metric_previous_analysis_uuid[trend_item["metric_id"].to_i] = 1
end
if metric_count_per_snapshot_id[sid]
metric_count_per_snapshot_id[sid] += 1
if metric_count_per_analysis_uuid[analysis_uuid]
metric_count_per_analysis_uuid[analysis_uuid] += 1
else
metric_count_per_snapshot_id[sid] = 1
metric_count_per_analysis_uuid[analysis_uuid] = 1
end
metric_data_map[trend_item["metric_id"].to_i] << {:date => Time.at(trend_item["created_at"].to_i/1000), :value => trend_item["value"], :sid => trend_item["sid"]}
metric_data_map[trend_item["metric_id"].to_i] << {:date => Time.at(trend_item["created_at"].to_i/1000), :value => trend_item["value"], :analysis_uuid => trend_item["analysis_uuid"]}
end

# Create JS structures to print out in the HTML page
@@ -83,7 +83,7 @@
js_data += "["
metric_data_map[metric_id].each() do |metric_data|
# for every metric value, we need to check that the corresponding snapshot has values for each metric
if metric_count_per_snapshot_id[metric_data[:sid]]==total_number_of_metrics
if metric_count_per_analysis_uuid[metric_data[:analysis_uuid]]==total_number_of_metrics
m_date = metric_data[:date]
m_value = sprintf("%0.02f", metric_data[:value])
m_value_localized = ProjectMeasure.new(:metric => metric_map[metric_id]).format_numeric_value(metric_data[:value], {})
@@ -107,9 +107,9 @@
js_data += "\"},"
if index == 0
# we fill the js_snapshots array (no need to do this more than once)
js_snapshots += "{sid:"
js_snapshots += metric_data[:sid].to_s
js_snapshots += ",d:\""
js_snapshots += "{sid:\""
js_snapshots += metric_data[:analysis_uuid]
js_snapshots += "\",d:\""
js_snapshots += human_short_date m_date
js_snapshots += "\"},"
end
@@ -143,9 +143,9 @@
js_events = "["
events.keys().sort.each() do |e_date|
e_details = events[e_date]
js_events += "{sid:"
js_events += e_details[0].snapshot.id.to_s
js_events += ",d:d("
js_events += "{sid:\""
js_events += e_details[0].analysis_uuid
js_events += "\",d:d("
js_events += e_date.year.to_s
js_events += ","
# Need to decrease by 1 the month as the JS Date object start months at 0 (= January)

+ 0
- 4
server/sonar-server/src/test/java/org/sonar/server/measure/MeasureFilterExecutorTest.java View File

@@ -488,10 +488,6 @@ public class MeasureFilterExecutorTest {
public void escape_percent_and_underscore_when_filter_by_component_name_or_key() throws SQLException {
db.prepareDbUnit(getClass(), "escape_percent_and_underscore_when_filter_by_component_name_or_key.xml");

// assertThat(executor.execute(
// new MeasureFilter().setResourceQualifiers(newArrayList("FIL")).setResourceKey("java_"),
// new MeasureFilterContext())).hasSize(2);

assertThat(executor.execute(
new MeasureFilter().setResourceQualifiers(newArrayList("FIL")).setResourceName("java%"),
new MeasureFilterContext())).hasSize(2);

+ 1
- 1
server/sonar-web/src/main/webapp/WEB-INF/app/controllers/api/events_controller.rb View File

@@ -137,7 +137,7 @@ class Api::EventsController < Api::ApiController
end
raise "A version already exists on this resource." if params[:category]==EventCategory::KEY_VERSION && root_snapshot.event(EventCategory::KEY_VERSION)
raise "An event '#{params[:name]}' (category '#{params[:category]}') already exists on this resource." if Event.already_exists(@resource.last_snapshot.id, params[:name], params[:category])
raise "An event '#{params[:name]}' (category '#{params[:category]}') already exists on this resource." if Event.already_exists(@resource.last_analysis.id, params[:name], params[:category])
# Create events for the root project and every submodule
event_to_return = nil

+ 49
- 49
server/sonar-web/src/main/webapp/WEB-INF/app/controllers/api/resources_controller.rb View File

@@ -104,7 +104,7 @@ class Api::ResourcesController < Api::ApiController
resource_id=params[:resource]
if resource_id
@resource=Project.by_key(resource_id)
@analysis=(@resource && @resource.last_snapshot)
@analysis=(@resource && @resource.last_analysis)
raise ApiException.new(404, "Resource [#{resource_id}] not found") if @analysis.nil?
raise ApiException.new(401, "Unauthorized") unless has_role?(:user, @resource)
else
@@ -195,7 +195,7 @@ class Api::ResourcesController < Api::ApiController

# ---------- LOAD COMPONENTS
# H2 does not support empty lists, so short-breaking if no measures
if load_measures && measures_by_component_uuid.empty?
if measures_limit && measures_by_component_uuid.empty?
components = []
else
components = Project.all(
@@ -284,7 +284,7 @@ class Api::ResourcesController < Api::ApiController
xml.resources do
components.each do |component|
measures = measures_by_component_uuid[component.uuid]
resource_to_xml(xml, component, measures, params)
component_to_xml(xml, component, measures, params)
end
end
end
@@ -310,26 +310,26 @@ class Api::ResourcesController < Api::ApiController
json['version']= component.last_analysis.version if component.last_analysis && component.last_analysis.version
json['branch']=component.branch if component.branch
json['description']=component.description if component.description
if include_trends && component.last_snapshot
json[:p1]=component.last_snapshot.period1_mode if component.last_snapshot.period1_mode
json[:p1p]=component.last_snapshot.period1_param if component.last_snapshot.period1_param
json[:p1d]=Api::Utils.format_datetime(component.last_snapshot.period1_date) if component.last_snapshot.period1_date
json[:p2]=component.last_snapshot.period2_mode if component.last_snapshot.period2_mode
json[:p2p]=component.last_snapshot.period2_param if component.last_snapshot.period2_param
json[:p2d]=Api::Utils.format_datetime(component.last_snapshot.period2_date) if component.last_snapshot.period2_date
json[:p3]=component.last_snapshot.period3_mode if component.last_snapshot.period3_mode
json[:p3p]=component.last_snapshot.period3_param if component.last_snapshot.period3_param
json[:p3d]=Api::Utils.format_datetime(component.last_snapshot.period3_date) if component.last_snapshot.period3_date
json[:p4]=component.last_snapshot.period4_mode if component.last_snapshot.period4_mode
json[:p4p]=component.last_snapshot.period4_param if component.last_snapshot.period4_param
json[:p4d]=Api::Utils.format_datetime(component.last_snapshot.period4_date) if component.last_snapshot.period4_date
json[:p5]=component.last_snapshot.period5_mode if component.last_snapshot.period5_mode
json[:p5p]=component.last_snapshot.period5_param if component.last_snapshot.period5_param
json[:p5d]=Api::Utils.format_datetime(component.last_snapshot.period5_date) if component.last_snapshot.period5_date
if include_trends && component.last_analysis
json[:p1]=component.last_snapshot.period1_mode if component.last_analysis.period1_mode
json[:p1p]=component.last_analysis.period1_param if component.last_analysis.period1_param
json[:p1d]=Api::Utils.format_datetime(component.last_analysis.period1_date) if component.last_analysis.period1_date
json[:p2]=component.last_analysis.period2_mode if component.last_analysis.period2_mode
json[:p2p]=component.last_analysis.period2_param if component.last_analysis.period2_param
json[:p2d]=Api::Utils.format_datetime(component.last_analysis.period2_date) if component.last_analysis.period2_date
json[:p3]=component.last_analysis.period3_mode if component.last_analysis.period3_mode
json[:p3p]=component.last_analysis.period3_param if component.last_analysis.period3_param
json[:p3d]=Api::Utils.format_datetime(component.last_analysis.period3_date) if component.last_analysis.period3_date
json[:p4]=component.last_analysis.period4_mode if component.last_analysis.period4_mode
json[:p4p]=component.last_analysis.period4_param if component.last_analysis.period4_param
json[:p4d]=Api::Utils.format_datetime(component.last_analysis.period4_date) if component.last_analysis.period4_date
json[:p5]=component.last_analysis.period5_mode if component.last_analysis.period5_mode
json[:p5p]=component.last_analysis.period5_param if component.last_analysis.period5_param
json[:p5d]=Api::Utils.format_datetime(component.last_analysis.period5_date) if component.last_analysis.period5_date
end
if measures
json_measures=[]
@@ -365,7 +365,7 @@ class Api::ResourcesController < Api::ApiController
json
end

def resource_to_xml(xml, component, measures, options={})
def component_to_xml(xml, component, measures, options={})
verbose=(options[:verbose]=='true')
include_alerts=(options[:includealerts]=='true')
include_trends=(options[:includetrends]=='true')
@@ -380,31 +380,31 @@ class Api::ResourcesController < Api::ApiController
xml.scope(component.scope)
xml.qualifier(component.qualifier)
xml.lang(component.language) if component.language
xml.version(snapshot.version) if snapshot.version
xml.date(Api::Utils.format_datetime(snapshot.created_at))
xml.creationDate(Api::Utils.format_datetime(resource.created_at))
xml.description(resource.description) if include_descriptions && resource.description
if include_trends && component.last_snapshot
xml.period1(component.last_snapshot.period1_mode) if component.last_snapshot.period1_mode
xml.period1_param(component.last_snapshot.period1_param) if component.last_snapshot.period1_param
xml.period1_date(Api::Utils.format_datetime(component.last_snapshot.period1_date)) if component.last_snapshot.period1_date
xml.period2(component.last_snapshot.period2_mode) if component.last_snapshot.period2_mode
xml.period2_param(component.last_snapshot.period2_param) if component.last_snapshot.period2_param
xml.period2_date(Api::Utils.format_datetime(component.last_snapshot.period2_date)) if component.last_snapshot.period2_date
xml.period3(component.last_snapshot.period3_mode) if component.last_snapshot.period3_mode
xml.period3_param(component.last_snapshot.period3_param) if component.last_snapshot.period3_param
xml.period3_date(Api::Utils.format_datetime(component.last_snapshot.period3_date)) if component.last_snapshot.period3_date
xml.period4(component.last_snapshot.period4_mode) if component.last_snapshot.period4_mode
xml.period4_param(component.last_snapshot.period4_param) if component.last_snapshot.period4_param
xml.period4_date(Api::Utils.format_datetime(component.last_snapshot.period4_date)) if component.last_snapshot.period4_date
xml.period5(component.last_snapshot.period5_mode) if component.last_snapshot.period5_mode
xml.period5_param(component.last_snapshot.period5_param) if component.last_snapshot.period5_param
xml.period5_date(Api::Utils.format_datetime(component.last_snapshot.period5_date)) if component.last_snapshot.period5_date
xml.version(component.last_analysis.version) if component.last_analysis && component.last_analysis.version
xml.date(Api::Utils.format_datetime(component.last_analysis.created_at)) if component.last_analysis
xml.creationDate(Api::Utils.format_datetime(component.created_at))
xml.description(component.description) if include_descriptions && component.description
if include_trends && component.last_analysis
xml.period1(component.last_analysis.period1_mode) if component.last_analysis.period1_mode
xml.period1_param(component.last_analysis.period1_param) if component.last_analysis.period1_param
xml.period1_date(Api::Utils.format_datetime(component.last_analysis.period1_date)) if component.last_analysis.period1_date
xml.period2(component.last_analysis.period2_mode) if component.last_analysis.period2_mode
xml.period2_param(component.last_analysis.period2_param) if component.last_analysis.period2_param
xml.period2_date(Api::Utils.format_datetime(component.last_analysis.period2_date)) if component.last_analysis.period2_date
xml.period3(component.last_analysis.period3_mode) if component.last_analysis.period3_mode
xml.period3_param(component.last_analysis.period3_param) if component.last_analysis.period3_param
xml.period3_date(Api::Utils.format_datetime(component.last_analysis.period3_date)) if component.last_analysis.period3_date
xml.period4(component.last_analysis.period4_mode) if component.last_analysis.period4_mode
xml.period4_param(component.last_analysis.period4_param) if component.last_analysis.period4_param
xml.period4_date(Api::Utils.format_datetime(component.last_analysis.period4_date)) if component.last_analysis.period4_date
xml.period5(component.last_analysis.period5_mode) if component.last_analysis.period5_mode
xml.period5_param(component.last_analysis.period5_param) if component.last_analysis.period5_param
xml.period5_date(Api::Utils.format_datetime(component.last_analysis.period5_date)) if component.last_analysis.period5_date
end

if measures

+ 3
- 3
server/sonar-web/src/main/webapp/WEB-INF/app/controllers/comparison_controller.rb View File

@@ -30,9 +30,9 @@ class ComparisonController < ApplicationController
project = Project.by_key(resource_key)
return render_not_found('Project not found') unless project

snapshots = project.events.select { |event| !event.snapshot.nil? && event.category==EventCategory::KEY_VERSION }[0..5].reverse.map {|e| e.snapshot}
snapshots = project.events.select { |event| event.snapshot && event.category==EventCategory::KEY_VERSION }[0..5].reverse.map {|e| e.snapshot}
# if last snapshot is not in the list, add it at the end (=> might be the case for views or developers which do not have events)
last_snapshot = project.last_snapshot
last_snapshot = project.last_analysis
unless snapshots.last == last_snapshot
snapshots.shift
snapshots.push(last_snapshot)
@@ -79,7 +79,7 @@ class ComparisonController < ApplicationController
@versions = project.events.select { |event| event.category==EventCategory::KEY_VERSION && !suuids.include?(event.analysis_uuid.to_s) }

# check if the latest snapshot if suggested or not (and if not, suggest it as "LATEST" => this is used for views or developers which do not have events)
latest_snapshot_uuid = project.last_snapshot.uuid
latest_snapshot_uuid = project.last_analysis.uuid
current_and_suggested_suuids = suuids + @versions.map {|e| e.analysis_uuid.to_s}
unless current_and_suggested_suuids.include?(latest_snapshot_uuid.to_s)
@versions.unshift Event.new(:name => Api::Utils.message('comparison.version.latest'), :analysis_uuid => latest_snapshot_uuid)

+ 1
- 1
server/sonar-web/src/main/webapp/WEB-INF/app/controllers/project_controller.rb View File

@@ -218,7 +218,7 @@ class ProjectController < ApplicationController
redirect_to :action => 'index', :id => params[:id]
end

@snapshot = @project.last_snapshot
@snapshot = @project.last_analysis
@analyses = Snapshot.all(:conditions => ["status='P' AND component_uuid=?", @project.uuid],
:include => 'events', :order => 'snapshots.created_at DESC')
end

+ 0
- 28
server/sonar-web/src/main/webapp/WEB-INF/app/models/chart_measure.rb View File

@@ -1,28 +0,0 @@
#
# SonarQube, open source software quality management tool.
# Copyright (C) 2008-2014 SonarSource
# mailto:contact AT sonarsource DOT com
#
# SonarQube 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.
#
# SonarQube 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
# License along with {library}; if not, write to the Free Software
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
class ChartMeasure
attr_accessor :time, :value
def initialize(time, value)
@time = time
@value = value
end

end

+ 0
- 22
server/sonar-web/src/main/webapp/WEB-INF/app/models/loaded_template.rb View File

@@ -1,22 +0,0 @@
#
# SonarQube, open source software quality management tool.
# Copyright (C) 2008-2014 SonarSource
# mailto:contact AT sonarsource DOT com
#
# SonarQube 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.
#
# SonarQube 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 this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
class LoadedTemplate < ActiveRecord::Base
end

+ 1
- 1
server/sonar-web/src/main/webapp/WEB-INF/app/models/measure_filter.rb View File

@@ -286,7 +286,7 @@ class MeasureFilter < ActiveRecord::Base
rows_by_component_uuid[component.uuid].set_analysis(analysis) if analysis
end

# @rows must be in the same order than the component uuids
# @rows must be in the same order as the component uuids
component_uuids.each do |uuid|
@rows << rows_by_component_uuid[uuid]
end

+ 5
- 31
server/sonar-web/src/main/webapp/WEB-INF/app/models/project.rb View File

@@ -32,7 +32,7 @@ class Project < ActiveRecord::Base
has_many :authors, :foreign_key => 'person_id', :dependent => :delete_all
has_one :index, :class_name => 'ResourceIndex', :foreign_key => 'component_uuid', :primary_key => 'uuid', :conditions => 'position=0', :select => 'kee'
has_many :resource_index, :foreign_key => 'resource_id'
has_one :last_analysis, :class_name => 'Snapshot', :foreign_key => 'component_uuid', :primary_key => 'uuid', :conditions => ['snapshots.islast=?', true]
has_one :last_analysis, :class_name => 'Snapshot', :foreign_key => 'component_uuid', :primary_key => 'project_uuid', :conditions => ['snapshots.islast=?', true]

def self.by_key(k)
begin
@@ -68,6 +68,10 @@ class Project < ActiveRecord::Base
root||self
end

def root?
project_uuid == uuid
end

def root_project
@root_project ||=
begin
@@ -141,17 +145,6 @@ class Project < ActiveRecord::Base
links.reject { |l| l.custom? }
end

def chart_measures(metric_id)
sql = Project.send(:sanitize_sql, ['select s.created_at as created_at, m.value as value ' +
' from project_measures m, snapshots s ' +
' where s.id=m.snapshot_id and ' +
" s.status='%s' and " +
' s.component_uuid=%s and m.metric_id=%s ', 'P', self.uuid, metric_id]) +
' and m.person_id IS NULL' +
' order by s.created_at'
create_chart_measures(Project.connection.select_all(sql), 'created_at', 'value')
end

def <=>(other)
kee <=> other.kee
end
@@ -184,25 +177,6 @@ class Project < ActiveRecord::Base

private

def create_chart_measures(results, date_column_name, value_column_name)
chart_measures = []
if results and results.first != nil
# :sanitize_sql is protected so its behaviour cannot be predicted exactly,
# the jdbc active record impl adapter returns a db typed objects array
# when regular active record impl return string typed objects
if results.first[date_column_name].class == Time
results.each do |hash|
chart_measures << ChartMeasure.new(hash[date_column_name], hash[value_column_name])
end
else
results.each do |hash|
chart_measures << ChartMeasure.new(Time.parse(hash[date_column_name]), hash[value_column_name].to_d)
end
end
end
chart_measures
end

def parent_module(current_module)
current_module.root.uuid = current_module.uuid ? current_module : parent_module(current_module.root)
end

+ 3
- 26
server/sonar-web/src/main/webapp/WEB-INF/app/models/snapshot.rb View File

@@ -65,29 +65,6 @@ class Snapshot < ActiveRecord::Base
Time.at(date_in_long/1000) if date_in_long
end

def self.for_timemachine_matrix(resource)
# http://jira.sonarsource.com/browse/SONAR-1850
# Conditions on scope and qualifier are required to exclude library snapshots.
# Use-case :
# 1. project A 2.0 is analyzed -> new snapshot A with qualifier TRK
# 2. project B, which depends on A 1.0, is analyzed -> new snapshot A 1.0 with qualifier LIB.
# 3. project A has 2 snapshots : the first one with qualifier=TRK has measures, the second one with qualifier LIB has no measures. Its version must not be used in time machine
# That's why the 2 following SQL requests check the qualifiers (and optionally scopes, just to be sure)
snapshots=Snapshot.find(:all, :conditions => ["snapshots.component_uuid=? AND events.analysis_uuid=snapshots.uuid AND snapshots.status=? AND snapshots.scope=? AND snapshots.qualifier=?", resource.uuid, STATUS_PROCESSED, resource.scope, resource.qualifier],
:include => 'events',
:order => 'snapshots.created_at ASC')

snapshots<<resource.last_snapshot if snapshots.empty?

snapshots=snapshots[-5, 5] if snapshots.size>=5

snapshots.insert(0, Snapshot.find(:first,
:conditions => ["component_uuid=? AND status=? AND scope=? AND qualifier=?", resource.uuid, STATUS_PROCESSED, resource.scope, resource.qualifier],
:include => 'project', :order => 'snapshots.created_at ASC', :limit => 1))

snapshots.compact.uniq
end

def self.for_timemachine_widget(resource, number_of_columns, options={})
if number_of_columns == 1
# Display only the latest snapshot
@@ -95,13 +72,13 @@ class Snapshot < ActiveRecord::Base
end

# Get 1rst & latests snapshots of the period
snapshot_conditions = ["snapshots.component_uuid=? AND snapshots.status=? AND snapshots.scope=? AND snapshots.qualifier=?", resource.uuid, STATUS_PROCESSED, resource.scope, resource.qualifier]
snapshot_conditions = ["snapshots.component_uuid=? AND snapshots.status=?", resource.project_uuid, STATUS_PROCESSED]
if options[:from]
snapshot_conditions[0] += " AND snapshots.created_at>=?"
snapshot_conditions << options[:from].to_i * 1000
end
first_snapshot=Snapshot.find(:first, :conditions => snapshot_conditions, :order => 'snapshots.created_at ASC')
last_snapshot=resource.last_snapshot
first_snapshot = Snapshot.find(:first, :conditions => snapshot_conditions, :order => 'snapshots.created_at ASC')
last_snapshot = resource.last_analysis

if first_snapshot==last_snapshot
return [last_snapshot]

+ 13
- 10
server/sonar-web/src/main/webapp/WEB-INF/app/models/sonar/timemachine_row.rb View File

@@ -22,15 +22,15 @@ class Sonar::TimemachineRow

def initialize(metric)
@metric=metric
@measure_by_sid={}
@measures_by_analysis_uuid = {}
end

def add_measure(measure)
@measure_by_sid[measure.snapshot_id]=measure
@measures_by_analysis_uuid[measure.analysis_uuid] = measure
end

def measure(snapshot)
@measure_by_sid[snapshot.id]
def measure(analysis)
@measures_by_analysis_uuid[analysis.uuid]
end

def domain
@@ -41,14 +41,17 @@ class Sonar::TimemachineRow
(self.domain <=> other.domain).nonzero? || (self.metric.short_name <=> other.metric.short_name)
end

def sparkline
if metric.numeric? && @measure_by_sid.size > 1
def sparkline(analyses)
if metric.numeric? && @measures_by_analysis_uuid.size > 1
x = []
y = []
@measure_by_sid.values.each do |measure|
# date.to_f does not works under oracle
x << measure.snapshot.created_at.to_s(:number)
y << (measure.value.nil? ? 0 : measure.value)
analyses.each do |analysis|
m = measure(analysis)
if m
# date.to_f does not works under oracle
x << analysis.created_at.to_s(:number)
y << (m.value.nil? ? 0 : m.value)
end
end
[x, y]
else

+ 5
- 5
server/sonar-web/src/main/webapp/WEB-INF/app/models/trends_chart.rb View File

@@ -19,12 +19,12 @@
#
class TrendsChart

def self.time_machine_measures(resource, metric_ids, options={})
def self.time_machine_measures(component, metric_ids, options={})
unless metric_ids.empty?
sql= "select s.created_at as created_at, m.value as value, m.metric_id as metric_id, s.id as sid " +
" from project_measures m LEFT OUTER JOIN snapshots s ON s.id=m.snapshot_id " +
sql= "select s.created_at as created_at, m.value as value, m.metric_id as metric_id, s.uuid as analysis_uuid " +
" from project_measures m LEFT OUTER JOIN snapshots s ON s.uuid = m.analysis_uuid " +
" where s.status=? " +
" and s.component_uuid=? " +
" and m.component_uuid=? " +
" and m.metric_id in (?) " +
" and m.person_id is null"
if (options[:from])
@@ -34,7 +34,7 @@ class TrendsChart
sql += ' and s.created_at<=?'
end
sql += ' order by s.created_at ASC'
conditions=[sql, Snapshot::STATUS_PROCESSED, resource.uuid, metric_ids]
conditions=[sql, Snapshot::STATUS_PROCESSED, component.uuid, metric_ids]
if (options[:from])
conditions<<options[:from].to_i*1000
end

+ 2
- 2
server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_nolayout.html.erb View File

@@ -1,6 +1,6 @@
<div id="body" class="page">
<% if @snapshot %>
<div class="print"><h2><%= h @snapshot.project.name(true) %></h2></div>
<% if @resource %>
<div class="print"><h2><%= h @resource.name(true) %></h2></div>
<% end %>
<div class="hidden" id="messages-panel">
<div class="alert alert-danger hidden" id="error">

+ 1
- 1
server/sonar-web/src/main/webapp/WEB-INF/app/views/project/deletion.html.erb View File

@@ -1,6 +1,6 @@
<div class="page">
<%
if !@snapshot || @snapshot.root?
if !@snapshot || @project.root?
resource_qualifier = message('qualifier.' + @project.qualifier)
delete_resource_message = message('project_deletion.page', :params => resource_qualifier)
%>

+ 1
- 1
server/sonar-web/src/main/webapp/WEB-INF/app/views/project/history.html.erb View File

@@ -15,7 +15,7 @@
<code><%= h @project.key -%></code>
</div>

<% elsif @snapshot.root? %>
<% elsif @project.root? %>

<table id="project-history" class="data" style="width:1%">
<thead>

server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1255_fix_project_uuid_of_developers.rb → server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1255_fix_project_uuid_of_developer_projects.rb View File

@@ -21,9 +21,9 @@
#
# SonarQube 6.0
#
class FixProjectUuidOfDevelopers < ActiveRecord::Migration
class FixProjectUuidOfDeveloperProjects < ActiveRecord::Migration

def self.up
execute_java_migration('org.sonar.db.version.v60.FixProjectUuidOfDevelopers')
execute_java_migration('org.sonar.db.version.v60.FixProjectUuidOfDeveloperProjects')
end
end

+ 4
- 3
sonar-db/src/main/java/org/sonar/db/measure/MeasureQuery.java View File

@@ -45,9 +45,9 @@ public class MeasureQuery {
}

private MeasureQuery(List<String> componentUuids,
@Nullable Collection<Integer> metricIds,
@Nullable Collection<String> metricKeys,
@Nullable Long personId) {
@Nullable Collection<Integer> metricIds,
@Nullable Collection<String> metricKeys,
@Nullable Long personId) {
checkState(componentUuids != null, "Component UUIDs must be set");
checkState(metricIds == null || metricKeys == null, "Metric IDs and keys must not be set both");
this.componentUuids = componentUuids;
@@ -96,6 +96,7 @@ public class MeasureQuery {
private Long personId;

private Builder() {
// see MeasureQuery#builder()
}

public Builder setComponentUuids(List<String> componentUuids) {

+ 3
- 3
sonar-db/src/main/java/org/sonar/db/measure/PastMeasureDto.java View File

@@ -39,7 +39,7 @@ public class PastMeasureDto {
return value;
}

public PastMeasureDto setValue(@Nullable Double value) {
PastMeasureDto setValue(@Nullable Double value) {
this.value = value;
return this;
}
@@ -52,7 +52,7 @@ public class PastMeasureDto {
return metricId;
}

public PastMeasureDto setMetricId(int i) {
PastMeasureDto setMetricId(int i) {
this.metricId = i;
return this;
}
@@ -62,7 +62,7 @@ public class PastMeasureDto {
return personId;
}

public PastMeasureDto setPersonId(@Nullable Long l) {
PastMeasureDto setPersonId(@Nullable Long l) {
this.personId = l;
return this;
}

+ 2
- 2
sonar-db/src/main/java/org/sonar/db/version/MigrationStepModule.java View File

@@ -115,7 +115,7 @@ import org.sonar.db.version.v60.DropSnapshotIdColumnFromCeActivity;
import org.sonar.db.version.v60.DropSnapshotIdColumnFromEvents;
import org.sonar.db.version.v60.DropSnapshotIdColumnsFromDuplicationsIndex;
import org.sonar.db.version.v60.DropUnusedMeasuresColumns;
import org.sonar.db.version.v60.FixProjectUuidOfDevelopers;
import org.sonar.db.version.v60.FixProjectUuidOfDeveloperProjects;
import org.sonar.db.version.v60.MakeAnalysisUuidNotNullOnDuplicationsIndex;
import org.sonar.db.version.v60.MakeAnalysisUuidNotNullOnEvents;
import org.sonar.db.version.v60.MakeAnalysisUuidNotNullOnMeasures;
@@ -288,7 +288,7 @@ public class MigrationStepModule extends Module {
MakeAnalysisUuidNotNullOnEvents.class,
DropSnapshotIdColumnFromEvents.class,

FixProjectUuidOfDevelopers.class,
FixProjectUuidOfDeveloperProjects.class,
// PROJECTS.UUID_PATH
AddUuidPathColumnToProjects.class,
PopulateUuidPathColumnOnProjects.class,

sonar-db/src/main/java/org/sonar/db/version/v60/FixProjectUuidOfDevelopers.java → sonar-db/src/main/java/org/sonar/db/version/v60/FixProjectUuidOfDeveloperProjects.java View File

@@ -26,22 +26,22 @@ import org.sonar.db.version.MassUpdate;
import org.sonar.db.version.Select;
import org.sonar.db.version.SqlStatement;

public class FixProjectUuidOfDevelopers extends BaseDataChange {
public class FixProjectUuidOfDeveloperProjects extends BaseDataChange {

public FixProjectUuidOfDevelopers(Database db) {
public FixProjectUuidOfDeveloperProjects(Database db) {
super(db);
}

@Override
public void execute(Context context) throws SQLException {
MassUpdate massUpdate = context.prepareMassUpdate();
massUpdate.select("select distinct developer_uuid from projects where qualifier = 'DEV_PRJ'");
massUpdate.update("update projects set project_uuid = developer_uuid where developer_uuid = ? and qualifier = 'DEV_PRJ'");
massUpdate.select("select distinct developer_uuid from projects where qualifier = 'DEV_PRJ' and project_uuid != developer_uuid");
massUpdate.update("update projects set project_uuid = developer_uuid where developer_uuid = ? and qualifier = 'DEV_PRJ' and project_uuid != developer_uuid");
massUpdate.rowPluralName("developers in project");
massUpdate.execute((row, update) -> handleComponent(row, update));
massUpdate.execute(FixProjectUuidOfDeveloperProjects::handleComponent);
}

private boolean handleComponent(Select.Row row, SqlStatement update) throws SQLException {
private static boolean handleComponent(Select.Row row, SqlStatement update) throws SQLException {
String developerUuid = row.getString(1);
update.setString(1, developerUuid);


sonar-db/src/test/java/org/sonar/db/version/v60/FixProjectUuidOfDevelopersTest.java → sonar-db/src/test/java/org/sonar/db/version/v60/FixProjectUuidOfDeveloperProjectsTest.java View File

@@ -29,7 +29,7 @@ import org.sonar.db.DbTester;

import static org.assertj.core.api.Assertions.assertThat;

public class FixProjectUuidOfDevelopersTest {
public class FixProjectUuidOfDeveloperProjectsTest {

private static final String TABLE_PROJECTS = "projects";
private static final String PROJECT_UUID = "U1";
@@ -39,10 +39,10 @@ public class FixProjectUuidOfDevelopersTest {
private static final String DEV2_IN_PROJECT_UUID = "U5";

@Rule
public DbTester db = DbTester.createForSchema(System2.INSTANCE, FixProjectUuidOfDevelopersTest.class,
public DbTester db = DbTester.createForSchema(System2.INSTANCE, FixProjectUuidOfDeveloperProjectsTest.class,
"in_progress_projects.sql");

private FixProjectUuidOfDevelopers underTest = new FixProjectUuidOfDevelopers(db.database());
private FixProjectUuidOfDeveloperProjects underTest = new FixProjectUuidOfDeveloperProjects(db.database());

@Test
public void migration_has_no_effect_on_empty_tables() throws SQLException {

sonar-db/src/test/resources/org/sonar/db/version/v60/FixProjectUuidOfDevelopersTest/in_progress_projects.sql → sonar-db/src/test/resources/org/sonar/db/version/v60/FixProjectUuidOfDeveloperProjectsTest/in_progress_projects.sql View File


Loading…
Cancel
Save