aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web
diff options
context:
space:
mode:
Diffstat (limited to 'server/sonar-web')
-rw-r--r--server/sonar-web/src/main/js/apps/drilldown/app.js48
-rw-r--r--server/sonar-web/src/main/js/components/shared/drilldown-link.js6
-rw-r--r--server/sonar-web/src/main/js/helpers/urls.js14
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/controllers/drilldown_controller.rb53
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/models/drilldown.rb167
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/views/drilldown/_footer.html.erb14
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/views/drilldown/measures.html.erb139
-rw-r--r--server/sonar-web/tests/helpers/urls-test.js9
-rw-r--r--server/sonar-web/webpack.config.js1
9 files changed, 8 insertions, 443 deletions
diff --git a/server/sonar-web/src/main/js/apps/drilldown/app.js b/server/sonar-web/src/main/js/apps/drilldown/app.js
deleted file mode 100644
index 276dd969d29..00000000000
--- a/server/sonar-web/src/main/js/apps/drilldown/app.js
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program 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.
- */
-import $ from 'jquery';
-import Marionette from 'backbone.marionette';
-import SourceViewer from '../../components/source-viewer/main';
-
-const App = new Marionette.Application();
-const init = function () {
- const options = window.sonarqube;
- App.addRegions({ viewerRegion: options.el });
- $('.js-drilldown-link').on('click', function (e) {
- e.preventDefault();
- $(e.currentTarget).closest('table').find('.selected').removeClass('selected');
- $(e.currentTarget).closest('tr').addClass('selected');
- const uuid = $(e.currentTarget).data('uuid');
- const viewer = new SourceViewer();
- App.viewerRegion.show(viewer);
- viewer.open(uuid);
- if (window.drilldown.period != null) {
- viewer.on('loaded', function () {
- viewer.filterLinesByDate(window.drilldown.period, window.drilldown.periodName);
- });
- }
- }).addClass('js-ready');
-};
-
-App.on('start', function (options) {
- init.call(App, options);
-});
-
-window.sonarqube.appStarted.then(options => App.start(options));
diff --git a/server/sonar-web/src/main/js/components/shared/drilldown-link.js b/server/sonar-web/src/main/js/components/shared/drilldown-link.js
index ea50a0390be..151021f9f95 100644
--- a/server/sonar-web/src/main/js/components/shared/drilldown-link.js
+++ b/server/sonar-web/src/main/js/components/shared/drilldown-link.js
@@ -132,10 +132,8 @@ export const DrilldownLink = React.createClass({
return this.renderIssuesLink();
}
- let highlightedMetric = HIGHLIGHT_MAPPING[this.props.metric];
- let url = highlightedMetric ?
- getComponentDrilldownUrl(this.props.component, highlightedMetric, this.props.period, this.props.metric) :
- getComponentDrilldownUrl(this.props.component, this.props.metric, this.props.period);
+ const highlightedMetric = HIGHLIGHT_MAPPING[this.props.metric] || this.props.metric;
+ const url = getComponentDrilldownUrl(this.props.component, highlightedMetric);
return <a className={this.props.className} href={url}>{this.props.children}</a>;
}
});
diff --git a/server/sonar-web/src/main/js/helpers/urls.js b/server/sonar-web/src/main/js/helpers/urls.js
index 96f26039701..7826f91227f 100644
--- a/server/sonar-web/src/main/js/helpers/urls.js
+++ b/server/sonar-web/src/main/js/helpers/urls.js
@@ -45,20 +45,10 @@ export function getComponentIssuesUrl (componentKey, query) {
* Generate URL for a component's drilldown page
* @param {string} componentKey
* @param {string} metric
- * @param {string|number} [period]
- * @param {string} [highlightedMetric]
* @returns {string}
*/
-export function getComponentDrilldownUrl (componentKey, metric, period, highlightedMetric) {
- let url = '/drilldown/measures?id=' + encodeURIComponent(componentKey) +
- '&metric=' + encodeURIComponent(metric);
- if (period) {
- url += '&period=' + period;
- }
- if (highlightedMetric) {
- url += '&highlight=' + encodeURIComponent(highlightedMetric);
- }
- return url;
+export function getComponentDrilldownUrl (componentKey, metric) {
+ return `/component_measures/${metric}?id=${encodeURIComponent(componentKey)}`;
}
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/drilldown_controller.rb b/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/drilldown_controller.rb
index 2010fc86433..3ef48fcabb2 100644
--- a/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/drilldown_controller.rb
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/drilldown_controller.rb
@@ -20,42 +20,11 @@
class DrilldownController < ApplicationController
before_filter :init_resource_for_user_role
- helper ProjectHelper, DashboardHelper, IssuesHelper
-
SECTION=Navigation::SECTION_RESOURCE
def measures
- @metric = select_metric(params[:metric], 'ncloc')
- @highlighted_metric = Metric.by_key(params[:highlight]) || @metric
-
- # selected resources
- if params[:rids]
- selected_rids= params[:rids]
- elsif params[:resource]
- highlighted_resource=Project.by_key(params[:resource])
- selected_rids=(highlighted_resource ? [highlighted_resource.id] : [])
- else
- selected_rids=[]
- end
- selected_rids=selected_rids.map { |r| r.to_i }
-
-
- # options
- options={}
- if params[:period] && Api::Utils.valid_period_index?(params[:period])
- @period=params[:period].to_i
- options[:period]=@period
- end
-
- # load data
- @drilldown = Drilldown.new(@resource, @metric, selected_rids, self, options)
-
- @highlighted_resource=@drilldown.highlighted_resource
- if @highlighted_resource.nil? && @drilldown.columns.empty?
- @highlighted_resource=@resource
- end
-
- @display_viewers = display_metric_viewers?(@highlighted_resource || @resource)
+ metric = params[:metric] || 'ncloc'
+ return redirect_to("/component_measures/#{metric}?id=#{url_encode(@resource.key)}")
end
def issues
@@ -64,22 +33,4 @@ class DrilldownController < ApplicationController
@severity = params[:severity]
end
-
- private
-
- def select_metric(metric_key, default_key)
- metric=nil
- if metric_key
- metric=Metric::by_key(metric_key)
- end
- if metric.nil?
- metric=Metric::by_key(default_key)
- end
- metric
- end
-
- def display_metric_viewers?(resource)
- return resource.file?
- end
-
end
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/models/drilldown.rb b/server/sonar-web/src/main/webapp/WEB-INF/app/models/drilldown.rb
deleted file mode 100644
index 2da5ce2ba10..00000000000
--- a/server/sonar-web/src/main/webapp/WEB-INF/app/models/drilldown.rb
+++ /dev/null
@@ -1,167 +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 Drilldown
-
- attr_reader :resource, :metric, :selected_resource_ids, :controller, :selected_project_not_authorized
- attr_reader :snapshot, :columns, :highlighted_resource, :highlighted_snapshot
-
- def initialize(resource, metric, selected_resource_ids, controller, options={})
- @controller=controller
- @resource=resource
- @selected_resource_ids=selected_resource_ids||[]
- @metric=metric
- @snapshot=resource.last_snapshot
- @columns=[]
-
- if @snapshot
- column=DrilldownColumn.new(self, nil)
- while column.valid?
- column.init_measures(options)
- if column.display?
- @columns<<column
- if column.selected_snapshot
- @highlighted_snapshot=column.selected_snapshot
- @highlighted_resource=column.selected_snapshot.project
- # User should only access projects he's authorized to see.
- unless controller.has_role?(:user, (column.selected_snapshot.project.copy_resource_id || column.selected_snapshot.resource_id_for_authorization))
- @selected_project_not_authorized = true
- break
- end
- end
- end
- column=DrilldownColumn.new(self, column)
- end
- end
- end
-
- def display_value?
- ProjectMeasure.exists?(["snapshot_id=? and metric_id=? and value is not null", @snapshot.id, @metric.id])
- end
-
- def display_period?(period_index)
- ProjectMeasure.exists?(["snapshot_id=? and metric_id=? and variation_value_#{period_index.to_i} is not null", @snapshot.id, @metric.id])
- end
-end
-
-
-class DrilldownColumn
-
- attr_reader :measures, :base_snapshot, :selected_snapshot, :qualifiers, :person_id
-
- def initialize(drilldown, previous_column)
- @drilldown = drilldown
-
- if previous_column
- @base_snapshot=(previous_column.selected_snapshot || previous_column.base_snapshot)
- @person_id=(previous_column.person_id || @base_snapshot.resource.person_id)
- else
- @base_snapshot=drilldown.snapshot
- @person_id=@base_snapshot.resource.person_id
- end
-
- # switch
- if @base_snapshot.resource.copy_resource
- @base_snapshot=@base_snapshot.resource.copy_resource.last_snapshot
- @qualifiers = @base_snapshot.children_qualifiers
-
- elsif previous_column
- @qualifiers=previous_column.qualifiers.map { |q| Java::OrgSonarServerUi::JRubyFacade.getInstance().getResourceChildrenQualifiers(q).to_a }.flatten
-
- else
- @qualifiers=drilldown.snapshot.children_qualifiers
- end
- @resource_per_sid={}
- end
-
- def init_measures(options)
- value_column = (options[:period] ? "variation_value_#{options[:period]}" : 'value')
- order="project_measures.#{value_column}"
- if @drilldown.metric.direction<0
- order += ' DESC'
- end
-
- conditions="snapshots.root_snapshot_id=:root_sid AND snapshots.islast=:islast AND snapshots.qualifier in (:qualifiers) " +
- " AND snapshots.path LIKE :path AND project_measures.metric_id=:metric_id AND project_measures.#{value_column} IS NOT NULL"
- condition_values={
- :root_sid => (@base_snapshot.root_snapshot_id || @base_snapshot.id),
- :islast => true,
- :qualifiers => @qualifiers,
- :metric_id => @drilldown.metric.id,
- :path => "#{@base_snapshot.path}#{@base_snapshot.id}.%"}
-
- if value_column=='value' && @drilldown.metric.best_value
- conditions<<' AND project_measures.value<>:best_value'
- condition_values[:best_value]=@drilldown.metric.best_value
- end
-
- if options[:exclude_zero_value] || (options[:period] && !@drilldown.metric.on_new_code?)
- conditions += " AND project_measures.#{value_column}<>0"
- end
-
- if options[:rule_id]
- conditions += ' AND project_measures.rule_id=:rule'
- condition_values[:rule]=options[:rule_id]
- else
- conditions += ' AND project_measures.rule_id IS NULL '
- end
-
- if @person_id
- conditions += ' AND project_measures.person_id=:person_id'
- condition_values[:person_id]=@person_id
- else
- conditions += ' AND project_measures.person_id IS NULL'
- end
-
- @measures=ProjectMeasure.all(
- :select => "project_measures.id,project_measures.metric_id,project_measures.#{value_column},project_measures.text_value,project_measures.alert_status,project_measures.alert_text,project_measures.snapshot_id",
- :joins => :snapshot,
- :conditions => [conditions, condition_values],
- :order => order,
- :limit => 200)
-
- @resource_per_sid={}
- sids=@measures.map { |m| m.snapshot_id }.compact.uniq
- unless sids.empty?
- snapshots = Snapshot.all(:include => :project, :conditions => {'snapshots.id' => sids})
- snapshots.each do |snapshot|
- @resource_per_sid[snapshot.id]=snapshot.project
- if @drilldown.selected_resource_ids.include?(snapshot.project_id)
- @selected_snapshot=snapshot
- end
- end
- end
- end
-
- def resource(measure)
- @resource_per_sid[measure.snapshot_id]
- end
-
- def display?
- @measures && !@measures.empty?
- end
-
- def valid?
- @base_snapshot && @qualifiers && !@qualifiers.empty?
- end
-
- def switch?
- selected_snapshot && selected_snapshot.resource && selected_snapshot.resource.copy_resource
- end
-end
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/drilldown/_footer.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/drilldown/_footer.html.erb
deleted file mode 100644
index 17986d4857f..00000000000
--- a/server/sonar-web/src/main/webapp/WEB-INF/app/views/drilldown/_footer.html.erb
+++ /dev/null
@@ -1,14 +0,0 @@
-<div id="resource_container"> </div>
-
-<%
- if @display_viewers
- resource = @drilldown.highlighted_resource || @drilldown.resource
- if resource
-%>
- <script>
- d(<%= resource.id -%>, <%= resource.source_code? -%>);
- </script>
-<%
- end
- end
-%>
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/drilldown/measures.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/drilldown/measures.html.erb
deleted file mode 100644
index f31229f1407..00000000000
--- a/server/sonar-web/src/main/webapp/WEB-INF/app/views/drilldown/measures.html.erb
+++ /dev/null
@@ -1,139 +0,0 @@
-<div class="page">
- <% if params[:period] && @snapshot.project_snapshot.periods? %>
- <div id="snapshot_title" class="spacer-bottom">
- <h4>
- <form method="GET" action="/drilldown/measures" style="display: inline">
- <input type="hidden" name="id" value="<%= h @snapshot.project.key -%>"/>
- <input type="hidden" name="metric" value="<%= h params[:metric] -%>"/>
- <% if params[:highlight] %>
- <input type="hidden" name="highlight" value="<%= h params[:highlight] -%>"/>
- <% end -%>
-
- <select id="select-comparison" name="period" onchange="submit()">
- <% if @drilldown.display_value? %>
- <option value=""><%= message('time_changes') -%>...</option>
- <% end %>
- <% for period_index in 1..5 do %>
- <%= period_select_options(@snapshot, period_index) if @drilldown.display_period?(period_index) -%>
- <% end %>
- </select>
- <script>
- $j(function () {
- $j('#select-comparison').select2({
- width: '300px',
- minimumResultsForSearch: 10,
- dropdownCssClass: 'small'
- });
- });
- </script>
- </form>
- </h4>
- </div>
- <% end %>
-
- <div class="marginbottom10">
- <h3><%= @highlighted_metric.short_name -%></h3>
-
- <p class="big">
- <%= format_measure(@snapshot.measure(@highlighted_metric.key), :period => @period) %>
- </p>
- <% if @highlighted_metric!=@metric %>
- <p>
- <%= message('drilldown.drilldown_on') -%>&nbsp;
- <b><%= format_measure(@metric.key, :period => @period) -%> <%= @metric.short_name -%></b>
- </p>
- <% end %>
- </div>
-
- <% unless @drilldown.columns.size > 0 %>
- <div class="alert alert-info"><%= h message('drilldown.no_items_found') -%></div>
- <% end %>
-
- <div id="drilldown" class="width100">
- <%
- rids=[]
- first_column=true
- last_column = nil
- @drilldown.columns.each_with_index do |column, index|
- %>
- <% if first_column %>
- <table class="width100 spacer-bottom">
- <tr>
- <% end %>
-
- <td class="<%= 'spacer-left' unless first_column -%>" nowrap>
- <div class="scrollable" id="col_<%= index -%>">
- <table class="spaced">
- <% column.measures.each_with_index do |measure, row_index|
- resource=column.resource(measure)
- selected = column.selected_snapshot && column.selected_snapshot.project_id==resource.id
- clazz = cycle("even", "odd", :name => "col_#{index}")
- clazz = clazz + ' selected' if selected
- %>
- <tr class="<%= clazz -%>" id="row_<%= index -%>_<%= row_index -%>">
- <td nowrap>
- <% if resource.source_code? %>
- <a href="<%= url_for :controller => 'dashboard', :action => 'index', :id => resource.id, :period => @period, :metric => (@metric && @metric.key), :rule => @rule ? @rule.id : @severity -%>"
- onclick="window.open(this.href,'resource-<%= resource.key.parameterize -%>','scrollbars=1,resizable=1');return false;"
- id="popup-<%= resource.key.parameterize -%>" class="nolink"
- target="_blank"><i class="icon-detach" title="<%= message('new_window') -%>"></i></a>
- <% else %>
- <%= link_to(image_tag('zoom.png'), {:id => resource.id, :metric => @metric.id}, {:class => 'nolink'}) -%>
- <% end %>
- <%= qualifier_icon(resource) -%>&nbsp;
- <% if resource.source_code? %>
- <a href="#" title="<%= h resource.name(true) -%>" data-key="<%= resource.key -%>"
- data-uuid="<%= resource.uuid -%>" class="js-drilldown-link"><%= h resource.name(false) %></a>
- <% else %>
- <%= link_to(h(resource.name), params.merge({:only_path => true, :rids => (selected ? rids-[resource.id] : rids+[resource.id])})) -%>
- <% end %>
- </td>
- <td class="text-right">
- <%= format_measure(measure, :skip_span_id => true, :period => @period) -%>
- </td>
- </tr>
- <% end %>
- </table>
- </div>
- </td>
-
- <% if column.switch? || index==@drilldown.columns.size-1 %>
- </tr>
- </table>
- <% end
- first_column = column.switch?
- rids<<column.selected_snapshot.project_id if column.selected_snapshot
- last_column = column
- end
- %>
- <% if last_column && @drilldown.selected_project_not_authorized %>
- <p class="notes"><%= message('not_authorized_to_access_project', {:params => last_column.selected_snapshot.project.name}) -%></p>
- <% end %>
- </div>
- <script>
- <% for i in 0...@drilldown.columns.size do %>
- $j('#col_<%= i -%> tr.selected').each(function (index, item) {
- item.scrollIntoView(true);
- });
- <% end %>
-
- window.drilldown = {
- metric: <% if @metric %>'<%= @metric.key -%>'<% else %>null<% end %>,
- rule: null,
- severity: null,
- period: <% if @period %>'<%= @snapshot.period_datetime(@period).strftime('%FT%T%z') -%>'<% else %>null<% end %>,
- periodName: <% if @period %>'<%= period_label(@snapshot, @period) -%>'<% else %>null<% end %>,
- };
- </script>
-
- <div id="source-viewer"></div>
-
- <%= render :partial => 'footer' -%>
-</div>
-
-<% content_for :extra_script do %>
- <script>
- window.sonarqube.el = '#source-viewer';
- </script>
- <script src="/js/bundles/drilldown.js?v=<%= sonar_version -%>"></script>
-<% end %>
diff --git a/server/sonar-web/tests/helpers/urls-test.js b/server/sonar-web/tests/helpers/urls-test.js
index e506ea427e4..b99f948c4b2 100644
--- a/server/sonar-web/tests/helpers/urls-test.js
+++ b/server/sonar-web/tests/helpers/urls-test.js
@@ -56,17 +56,12 @@ describe('URLs', function () {
describe('#getComponentDrilldownUrl', function () {
it('should return component drilldown url', function () {
expect(getComponentDrilldownUrl(SIMPLE_COMPONENT_KEY, METRIC)).to.equal(
- '/drilldown/measures?id=' + SIMPLE_COMPONENT_KEY + '&metric=' + METRIC);
+ '/component_measures/' + METRIC + '?id=' + SIMPLE_COMPONENT_KEY);
});
it('should encode component key', function () {
expect(getComponentDrilldownUrl(COMPLEX_COMPONENT_KEY, METRIC)).to.equal(
- '/drilldown/measures?id=' + COMPLEX_COMPONENT_KEY_ENCODED + '&metric=' + METRIC);
- });
-
- it('should work with period', function () {
- expect(getComponentDrilldownUrl(SIMPLE_COMPONENT_KEY, METRIC, PERIOD)).to.equal(
- '/drilldown/measures?id=' + SIMPLE_COMPONENT_KEY + '&metric=' + METRIC + '&period=' + PERIOD);
+ '/component_measures/' + METRIC + '?id=' + COMPLEX_COMPONENT_KEY_ENCODED);
});
});
});
diff --git a/server/sonar-web/webpack.config.js b/server/sonar-web/webpack.config.js
index 9c721550c2c..a441f2b2728 100644
--- a/server/sonar-web/webpack.config.js
+++ b/server/sonar-web/webpack.config.js
@@ -33,7 +33,6 @@ module.exports = {
'component-measures': './src/main/js/apps/component-measures/app.js',
'custom-measures': './src/main/js/apps/custom-measures/app.js',
'dashboard': './src/main/js/apps/dashboard/app.js',
- 'drilldown': './src/main/js/apps/drilldown/app.js',
'global-permissions': './src/main/js/apps/global-permissions/app.js',
'groups': './src/main/js/apps/groups/app.js',
'issues': './src/main/js/apps/issues/app.js',