]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-3672 improve the selection of projects in global dashboards
authorSimon Brandhof <simon.brandhof@gmail.com>
Wed, 19 Sep 2012 16:30:53 +0000 (18:30 +0200)
committerSimon Brandhof <simon.brandhof@gmail.com>
Wed, 19 Sep 2012 16:54:51 +0000 (18:54 +0200)
sonar-server/src/main/webapp/WEB-INF/app/controllers/api/resources_controller.rb
sonar-server/src/main/webapp/WEB-INF/app/controllers/dev_controller.rb [deleted file]
sonar-server/src/main/webapp/WEB-INF/app/helpers/application_helper.rb
sonar-server/src/main/webapp/WEB-INF/app/helpers/widget_properties_helper.rb
sonar-server/src/main/webapp/WEB-INF/app/models/widget.rb
sonar-server/src/main/webapp/WEB-INF/app/views/dashboard/_widget_properties.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/dev/form.html.erb [deleted file]
sonar-server/src/main/webapp/stylesheets/select2.css

index 9cb06f4a4c5e3b24c64b544b6fd82f93a3438209..959b15dbdec4e0f39aa8605eb005fa58f0ebc429 100644 (file)
 #
 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<ResourceIndex::MIN_SEARCH_SIZE
+      bad_request("Page index must be greater than 0") if page<=0
+      bad_request("Page size must be greater than 0") if page_size<=0
+
+      key = search_text.downcase
+      conditions=['kee like ?']
+      condition_values=[key + '%']
+
+      unless qualifiers.empty?
+        conditions<<'qualifier in (?)'
+        condition_values<<qualifiers
+      end
+      indexes = ResourceIndex.find(:all,
+                                   :select => '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 (file)
index 2242ba9..0000000
+++ /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
index fb2dbf84bd2877defd1bf84a5ab1dd2fe72b0baa..d3ca2a2bb35d4e1a65ea402d51904806b935db88 100644 (file)
@@ -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</a></span>"
   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' => <<FUNC
+function (data, page) {
+  var more=(data.page * data.page_size)<data.total;
+  var results=$j.map(data.data, function(elt, i) {
+    return {id: elt.id, text: elt.nm};
+  });
+  return {more: more, results: results};
+}
+FUNC
+    }
+    ajax_options.merge!(options[:select2_ajax_options]) if options[:select2_ajax_options]
+
+    js_options={'minimumInputLength' => 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 = "<input type='hidden' id='#{html_id}' name='#{name}' style='width:#{width}'/>"
+    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}<script>#{js}</script>"
+  end
+
 end
index f2e8f19a8a33d93d6d1bdaaee957863398413d1c..1f9841e809e2a800282f7d04fb1130db7a75f07b 100644 (file)
@@ -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
index 8ef74c38d328b3ebe57d22325b97d56d4b4e761e..61a5d51e0d2e0c09b294488efeb9546a6dbb709a 100644 (file)
@@ -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
index 79225aa2e7298c75f8cb5373f5f592b68d241b48..60b6fe9c99f3d0857a7618cbcda89edc2c13963f 100644 (file)
@@ -9,7 +9,9 @@
     <% if !widget.java_definition.global && @dashboard.global %>
       <tr>
         <td class="form-key-cell"><%= message('widget.resource_id') %> *</td>
-        <td class="form-val-cell" id="row_resource"><%= resource_value_field(widget.resource_id) -%></td>
+        <td class="form-val-cell" id="row_resource">
+          <%= resource_dropdown('resource_id', {:resource_type_property => 'supportsGlobalDashboards', :selected_resource => widget.resource, :width => '250px', :html_id => "sel-prj-#{widget.id}"}) -%>
+        </td>
       </tr>
     <% 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 (file)
index cb1a35b..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-Select a file:
-<select id="select-file" name="file" multiple="multiple" style="width: 300px">
-  <% Project.find(:all, :conditions => {:qualifier => ['FIL', 'CLA'], :enabled => true}, :order => 'name').each do |file| %>
-    <option value="<%= file.id -%>"><%= h file.name -%></option>
-  <% end %>
-</select>
-<script>
-  $j('#select-file').select2();
-</script>
\ No newline at end of file
index 1f87f10148da9af61c03654b1b05106a5b2473e3..746c8993703a7ae7754fd23925e505ff008216f8 100755 (executable)
@@ -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;