#
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]
+++ /dev/null
-#
-# 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
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.
html += message('reviews.remove_this_filter')
html += "\">X</a></span>"
end
-
+
#
# Compares 2 strings using the human natural order.
# For instance, the following array:
# 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
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
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
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
<% 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 %>
+++ /dev/null
-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
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;
display: block;
position: absolute;
right: 26px;
- top: 8px;
+ top: 4px;
width: 12px;
height: 12px;
font-size: 1px;
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));
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;
.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%;
}
.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 {
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;
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;
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;
}
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;