From f8d13b3860683187fca69c435309ef097f64983a Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Wed, 19 Sep 2012 18:30:53 +0200 Subject: [PATCH] SONAR-3672 improve the selection of projects in global dashboards --- .../controllers/api/resources_controller.rb | 48 ++++++++++++++ .../WEB-INF/app/controllers/dev_controller.rb | 44 ------------- .../WEB-INF/app/helpers/application_helper.rb | 48 +++++++++++++- .../app/helpers/widget_properties_helper.rb | 16 ----- .../main/webapp/WEB-INF/app/models/widget.rb | 1 + .../dashboard/_widget_properties.html.erb | 4 +- .../WEB-INF/app/views/dev/form.html.erb | 9 --- .../src/main/webapp/stylesheets/select2.css | 62 +++++++++++-------- 8 files changed, 134 insertions(+), 98 deletions(-) delete mode 100644 sonar-server/src/main/webapp/WEB-INF/app/controllers/dev_controller.rb delete mode 100644 sonar-server/src/main/webapp/WEB-INF/app/views/dev/form.html.erb diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/resources_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/resources_controller.rb index 9cb06f4a4c5..959b15dbdec 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/resources_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/resources_controller.rb @@ -19,6 +19,54 @@ # class Api::ResourcesController < Api::ApiController + def search + search_text = params[:s]||'' + page=(params[:p] ? params[:p].to_i : 1) + page_size=(params[:ps] ? params[:ps].to_i : 10) + if params[:q] + qualifiers=params[:q].split(',') + elsif params[:rtp] + qualifiers=Java::OrgSonarServerUi::JRubyFacade.getInstance().getQualifiersWithProperty(params[:rtp]) + else + qualifiers=[] + end + + bad_request("Minimum search is #{ResourceIndex::MIN_SEARCH_SIZE} characters") if search_text.size 'resource_id,root_project_id,qualifier', # optimization to not load unused columns like 'kee' + :conditions => [conditions.join(' and ')].concat(condition_values), + :order => 'name_size') + + indexes = select_authorized(:user, indexes) + total = indexes.size + offset=(page-1)*page_size + resource_ids=indexes[offset...offset+page_size].map { |index| index.resource_id } + + resources=[] + unless resource_ids.empty? + resources=Project.find(:all, :select => 'id,qualifier,name,long_name', :conditions => ['id in (?) and enabled=?', resource_ids, true]) + end + + json = {:total => total, :page => page, :page_size => page_size, :data => resources.map { |r| {:id => r.id, :nm => r.name(true), :q => r.qualifier} }} + + respond_to do |format| + format.json { render :json => jsonp(json) } + format.xml { render :xml => xml_not_supported } + format.text { render :text => text_not_supported } + end + end + def index begin resource_id=params[:resource] diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/dev_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/dev_controller.rb deleted file mode 100644 index 2242ba9da58..00000000000 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/dev_controller.rb +++ /dev/null @@ -1,44 +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 DevController < ApplicationController - - SECTION=Navigation::SECTION_HOME - - # some actions load secured information - before_filter :admin_required - - def layout - render :text => '', :layout => true - end - - def empty - render :text => '' - end - - def breadcrumb - files = Project.find(:all, :conditions => {:qualifier => ['FIL', 'CLA'], :enabled => true}) - @resource = files[0] unless files.empty? - render :text => '', :layout => true - end - - def form - - end -end 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 fb2dbf84bd2..d3ca2a2bb35 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 @@ -554,7 +554,7 @@ module ApplicationHelper html end - + # # Used on the reviews listing page (http://localhost:9000/project_reviews) # Prints a label for the given parameter that is used to filter the review list. @@ -576,7 +576,7 @@ module ApplicationHelper html += message('reviews.remove_this_filter') html += "\">X" end - + # # Compares 2 strings using the human natural order. # For instance, the following array: @@ -611,7 +611,7 @@ module ApplicationHelper # Compare the non-digits case (chars1 <=> chars2) - when 0 + when 0 # Non-digits are the same, compare the digits... # If either number begins with a zero, then compare # alphabetically, otherwise compare numerically @@ -633,4 +633,46 @@ module ApplicationHelper return 0 end + def resource_dropdown(name, options={}) + width=options[:width] + html_id=options[:html_id]||name + + ws_url="#{ApplicationController::root_context}/api/resources/search?" + if options[:qualifiers] + ws_url+="q=#{options[:qualifiers].join(',')}" + elsif options[:resource_type_property] + ws_url+="rtp=#{options[:resource_type_property]}" + end + + ajax_options={ + 'quietMillis' => 300, + 'url' => "'#{ws_url}'", + 'data' => 'function (term, page) {return {s:term, p:page}}', + 'results' => < options[:minimumInputLength]||3} + js_options['ajax']='{' + ajax_options.map{|k,v| "#{k}:#{v}"}.join(',') + '}' + js_options.merge!(options[:select2_options]) if options[:select2_options] + + html = "" + js = "$j('##{html_id}').select2({#{js_options.map{|k,v| "#{k}:#{v}"}.join(',')}});" + + resource = options[:selected_resource] + if resource + js += "$j('##{html_id}').select2('data', {id: #{resource.id}, text: '#{escape_javascript(resource.name(true))}'});" + end + + "#{html}" + end + end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/helpers/widget_properties_helper.rb b/sonar-server/src/main/webapp/WEB-INF/app/helpers/widget_properties_helper.rb index f2e8f19a8a3..1f9841e809e 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/helpers/widget_properties_helper.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/helpers/widget_properties_helper.rb @@ -24,21 +24,5 @@ module WidgetPropertiesHelper property_value definition.key(), definition.type.name(), value.nil? ? definition.defaultValue() : value end - def resource_value_field(value) - combo = '' - - visible_qualifiers=Java::OrgSonarServerUi::JRubyFacade.getInstance().getQualifiersWithProperty('supportsGlobalDashboards') - - visible_qualifiers.each do |qualifier| - projects = Project.all(:conditions => {:qualifier => qualifier, :enabled => true, :copy_resource_id => nil}) - - unless projects.nil? || projects.empty? - sorted_projects = Api::Utils.insensitive_sort(projects, &:name) - combo += option_group(message('qualifiers.' + qualifier), options_id(value, sorted_projects)) - end - end - - select_tag 'resource_id', combo - end end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/widget.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/widget.rb index 8ef74c38d32..61a5d51e0d2 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/models/widget.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/models/widget.rb @@ -20,6 +20,7 @@ class Widget < ActiveRecord::Base has_many :properties, :dependent => :delete_all, :class_name => 'WidgetProperty' belongs_to :dashboards + belongs_to :resource, :class_name => 'Project' validates_presence_of :widget_key validates_length_of :widget_key, :within => 1..256 diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/dashboard/_widget_properties.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/dashboard/_widget_properties.html.erb index 79225aa2e72..60b6fe9c99f 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/dashboard/_widget_properties.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/dashboard/_widget_properties.html.erb @@ -9,7 +9,9 @@ <% if !widget.java_definition.global && @dashboard.global %> <%= message('widget.resource_id') %> * - <%= resource_value_field(widget.resource_id) -%> + + <%= resource_dropdown('resource_id', {:resource_type_property => 'supportsGlobalDashboards', :selected_resource => widget.resource, :width => '250px', :html_id => "sel-prj-#{widget.id}"}) -%> + <% end %> diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/dev/form.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/dev/form.html.erb deleted file mode 100644 index cb1a35b9ff0..00000000000 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/dev/form.html.erb +++ /dev/null @@ -1,9 +0,0 @@ -Select a file: - - \ No newline at end of file diff --git a/sonar-server/src/main/webapp/stylesheets/select2.css b/sonar-server/src/main/webapp/stylesheets/select2.css index 1f87f10148d..746c8993703 100755 --- a/sonar-server/src/main/webapp/stylesheets/select2.css +++ b/sonar-server/src/main/webapp/stylesheets/select2.css @@ -47,8 +47,10 @@ Version: 3.2 Timestamp: Mon Sep 10 10:38:04 PDT 2012 overflow: hidden; white-space: nowrap; position: relative; - height: 26px; - line-height: 26px; + + /* sonar: reduce height */ + height: 20px; + line-height: 20px; padding: 0 0 0 8px; color: #444; text-decoration: none; @@ -82,7 +84,7 @@ Version: 3.2 Timestamp: Mon Sep 10 10:38:04 PDT 2012 display: block; position: absolute; right: 26px; - top: 8px; + top: 4px; width: 12px; height: 12px; font-size: 1px; @@ -139,6 +141,7 @@ Version: 3.2 Timestamp: Mon Sep 10 10:38:04 PDT 2012 border-radius: 0 4px 4px 0; -moz-background-clip: padding; -webkit-background-clip: padding-box; + /* sonar: customize selection arrow background-clip: padding-box; background: #ccc; background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #ccc), color-stop(0.6, #eee)); @@ -148,7 +151,11 @@ Version: 3.2 Timestamp: Mon Sep 10 10:38:04 PDT 2012 background-image: -ms-linear-gradient(top, #cccccc 0%, #eeeeee 60%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#cccccc', endColorstr = '#eeeeee', GradientType = 0); background-image: linear-gradient(top, #cccccc 0%, #eeeeee 60%); - border-left: 1px solid #aaa; + */ + + + /* sonar: customize selection arrow + border-left: 1px solid #aaa;*/ position: absolute; right: 0; top: 0; @@ -159,7 +166,7 @@ Version: 3.2 Timestamp: Mon Sep 10 10:38:04 PDT 2012 .select2-container .select2-choice div b { /* sonar : change path to png */ - background: url('../images/select2.png') no-repeat 0 1px; + background: url('../images/select2.png') no-repeat 0 -2px; display: block; width: 100%; height: 100%; @@ -408,7 +415,8 @@ disabled look for already selected choices in the results dropdown } .select2-container-multi .select2-choices { - min-height: 26px; + /* sonar : reduce height by 4 pixels */ + min-height: 20px; } .select2-container-multi.select2-container-active .select2-choices { @@ -421,25 +429,16 @@ disabled look for already selected choices in the results dropdown outline: none; } -.select2-container-multi .select2-choices li { - float: left; - list-style: none; -} - -.select2-container-multi .select2-choices .select2-search-field { - white-space: nowrap; - margin: 0; - padding: 0; -} - .select2-container-multi .select2-choices .select2-search-field input { color: #666; background: transparent !important; font-family: sans-serif; - font-size: 100%; - height: 15px; + /* sonar : reduce height by 4 pixels */ + font-size: 93%; + height: 11px; + margin: 0; + /* /sonar */ padding: 5px; - margin: 1px 0; outline: 0; border: 0; -webkit-box-shadow: none; @@ -448,6 +447,17 @@ disabled look for already selected choices in the results dropdown box-shadow: none; } +.select2-container-multi .select2-choices li { + float: left; + list-style: none; +} + +.select2-container-multi .select2-choices .select2-search-field { + white-space: nowrap; + margin: 0; + padding: 0; +} + .select2-container-multi .select2-choices .select2-search-field input.select2-active { /* sonar : change path to image */ background: #fff url('../images/spinner.gif') no-repeat 100% !important; @@ -477,9 +487,11 @@ disabled look for already selected choices in the results dropdown box-shadow: 0 0 2px #ffffff inset, 0 1px 0 rgba(0, 0, 0, 0.05); color: #333; border: 1px solid #aaaaaa; - line-height: 13px; - padding: 3px 5px 3px 18px; - margin: 3px 0 3px 5px; + /* sonar : reduce height */ + line-height: 11px; + font-size: 93%; + padding: 3px 5px 3px 15px; + margin: 1px 0 1px 1px; position: relative; cursor: default; } @@ -496,9 +508,9 @@ disabled look for already selected choices in the results dropdown display: block; position: absolute; right: 3px; - top: 4px; + top: 2px; width: 12px; - height: 13px; + height: 11px; font-size: 1px; /* sonar : change path to image */ background: url('../images/select2.png') right top no-repeat; -- 2.39.5