diff options
author | David Gageot <david@gageot.net> | 2012-09-20 17:05:20 +0200 |
---|---|---|
committer | David Gageot <david@gageot.net> | 2012-09-20 17:08:29 +0200 |
commit | bb889f52fb08f10a175ff64b65edd0929a5a69c6 (patch) | |
tree | cbbc50b4af05e3b62c92db250bd694b78e7452d8 /sonar-server/src | |
parent | 1b000a65c28f43a3242c55f91a0cc7f6a210e979 (diff) | |
download | sonarqube-bb889f52fb08f10a175ff64b65edd0929a5a69c6.tar.gz sonarqube-bb889f52fb08f10a175ff64b65edd0929a5a69c6.zip |
SONAR-3754 API: ability to define a cardinality on a property
Diffstat (limited to 'sonar-server/src')
14 files changed, 291 insertions, 295 deletions
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/authentication_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/authentication_controller.rb index 92d1c85d95c..5554c8f4728 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/authentication_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/authentication_controller.rb @@ -49,7 +49,7 @@ class Api::AuthenticationController < Api::ApiController end def force_authentication? - property = Property.find(:first, :conditions => {:prop_key => org.sonar.api.CoreProperties.CORE_FORCE_AUTHENTICATION_PROPERTY, :resource_id => nil, :user_id => nil}) + property = Property.by_key(org.sonar.api.CoreProperties.CORE_FORCE_AUTHENTICATION_PROPERTY) property ? property.value == 'true' : false end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/user_properties_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/user_properties_controller.rb index fb98e5b6f1f..4cab0f299cf 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/user_properties_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/user_properties_controller.rb @@ -43,7 +43,7 @@ class Api::UserPropertiesController < Api::ApiController # curl http://localhost:9000/api/user_properties/<key> -v -u admin:admin # def show - property = Property.find(:first, :conditions => ['user_id=? and prop_key=?', current_user.id, params[:id]]) + property = Property.by_key(params[:id], nil, current_user.id) if property respond_to do |format| format.json { render :json => jsonp(properties_to_json([property])) } @@ -65,7 +65,7 @@ class Api::UserPropertiesController < Api::ApiController value = params[:value] if key begin - Property.delete_all(['prop_key=? AND user_id=?', key,current_user.id]) + Property.clear(key, nil, current_user.id) property=Property.create(:prop_key => key, :text_value => value, :user_id => current_user.id) respond_to do |format| format.json { render :json => jsonp(properties_to_json([property])) } @@ -88,10 +88,9 @@ class Api::UserPropertiesController < Api::ApiController def destroy begin if params[:id] - Property.delete_all(['prop_key=? AND user_id=?', params[:id], current_user.id]) + Property.clear(params[:id], nil, current_user.id) end render_success("Property deleted") - rescue Exception => e logger.error("Fails to execute #{request.url} : #{e.message}") render_error(e.message) diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/project_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/project_controller.rb index de19cb7b14f..76918622d64 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/project_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/project_controller.rb @@ -18,7 +18,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 # class ProjectController < ApplicationController - verify :method => :post, :only => [:set_links, :set_exclusions, :delete_exclusions, :update_key, :perform_key_bulk_update, :update_quality_profile], + verify :method => :post, :only => [:set_links, :set_exclusions, :delete_exclusions, :update_key, :perform_key_bulk_update, :update_quality_profile], :redirect_to => {:action => :index} verify :method => :delete, :only => [:delete], :redirect_to => {:action => :index} @@ -33,11 +33,11 @@ class ProjectController < ApplicationController if java_facade.getResourceTypeBooleanProperty(@project.qualifier, 'deletable') deletion_manager = ResourceDeletionManager.instance - if deletion_manager.currently_deleting_resources? || + if deletion_manager.currently_deleting_resources? || (!deletion_manager.currently_deleting_resources? && deletion_manager.deletion_failures_occured?) # a deletion is happening or it has just finished with errors => display the message from the Resource Deletion Manager render :template => 'project/pending_deletion' - else + else @snapshot=@project.last_snapshot end else @@ -47,19 +47,19 @@ class ProjectController < ApplicationController def delete @project = get_current_project(params[:id]) - + # Ask the resource deletion manager to start the migration # => this is an asynchronous AJAX call ResourceDeletionManager.instance.delete_resources([@project.id]) - + # and return some text that will actually never be displayed render :text => ResourceDeletionManager.instance.message end - + def pending_deletion deletion_manager = ResourceDeletionManager.instance - - if deletion_manager.currently_deleting_resources? || + + if deletion_manager.currently_deleting_resources? || (!deletion_manager.currently_deleting_resources? && deletion_manager.deletion_failures_occured?) # display the same page again and again # => implicit render "pending_deletion.html.erb" @@ -67,24 +67,24 @@ class ProjectController < ApplicationController redirect_to_default end end - + def dismiss_deletion_message # It is important to reinit the ResourceDeletionManager so that the deletion screens can be available again ResourceDeletionManager.instance.reinit - + redirect_to :action => 'deletion', :id => params[:id] end - + def quality_profile @project = get_current_project(params[:id]) @profiles = Profile.find(:all, :conditions => {:language => @project.language, :enabled => true}) end - + def update_quality_profile project = get_current_project(params[:id]) - + selected_profile = Profile.find(:first, :conditions => {:id => params[:quality_profile].to_i}) - if selected_profile && selected_profile.language == project.language + if selected_profile && selected_profile.language == project.language project.profile = selected_profile project.save! flash[:notice] = message('project_quality_profile.profile_successfully_updated') @@ -92,17 +92,17 @@ class ProjectController < ApplicationController selected_profile_name = selected_profile ? selected_profile.name + "(" + selected_profile.language + ")" : "Unknown profile" flash[:error] = message('project_quality_profile.project_cannot_be_update_with_profile_x', :params => selected_profile_name) end - + redirect_to :action => 'quality_profile', :id => project.id end - + def key @project = get_current_project(params[:id]) end - + def update_key project = get_current_project(params[:id]) - + new_key = params[:new_key].strip if new_key.blank? flash[:error] = message('update_key.new_key_cant_be_blank_for_x', :params => project.key) @@ -115,17 +115,17 @@ class ProjectController < ApplicationController java_facade.updateResourceKey(project.id, new_key) flash[:notice] = message('update_key.key_updated') rescue Exception => e - flash[:error] = message('update_key.error_occured_while_renaming_key_of_x', + flash[:error] = message('update_key.error_occured_while_renaming_key_of_x', :params => [project.key, Api::Utils.exception_message(e, :backtrace => false)]) end end - + redirect_to :action => 'key', :id => project.root_project.id end - + def prepare_key_bulk_update @project = get_current_project(params[:id]) - + @string_to_replace = params[:string_to_replace].strip @replacement_string = params[:replacement_string].strip if @string_to_replace.blank? || @replacement_string.blank? @@ -148,20 +148,20 @@ class ProjectController < ApplicationController def perform_key_bulk_update project = get_current_project(params[:id]) - + string_to_replace = params[:string_to_replace].strip replacement_string = params[:replacement_string].strip - + unless string_to_replace.blank? || replacement_string.blank? begin java_facade.bulkUpdateKey(project.id, string_to_replace, replacement_string) flash[:notice] = message('update_key.key_updated') rescue Exception => e - flash[:error] = message('update_key.error_occured_while_renaming_key_of_x', + flash[:error] = message('update_key.error_occured_while_renaming_key_of_x', :params => [project.key, Api::Utils.exception_message(e, :backtrace => false)]) end end - + redirect_to :action => 'key', :id => project.id end @@ -224,32 +224,34 @@ class ProjectController < ApplicationController redirect_to :action => 'links', :id => project.id end - def settings - @project = get_current_project(params[:id]) + @resource = get_current_project(params[:id]) - @snapshot=@project.last_snapshot - if !@project.project? && !@project.module? + @snapshot = @resource.last_snapshot + if !@resource.project? && !@resource.module? redirect_to :action => 'index', :id => params[:id] end - @category=params[:category] ||= 'general' - @definitions_per_category={} - definitions = java_facade.getPropertyDefinitions() - properties = definitions.getAll().select { |property| (@project.module? && property.isOnModule()) || (@project.project? && property.isOnProject()) } - properties.each do |property| - category = definitions.getCategory(property.getKey()) - @definitions_per_category[category]||=[] - @definitions_per_category[category]<<property + if @resource.nil? + definitions_per_category = java_facade.propertyDefinitions.globalPropertiesByCategory + elsif @resource.project? + definitions_per_category = java_facade.propertyDefinitions.projectPropertiesByCategory + elsif @resource.module? + definitions_per_category = java_facade.propertyDefinitions.modulePropertiesByCategory end - end + @category = params[:category] || 'general' + @categories = definitions_per_category.keys + @definitions = definitions_per_category[@category] || [] + + not_found('category') unless @categories.include? @category + end def events @categories = EventCategory.categories(true) @snapshot = Snapshot.find(params[:id]) @category = params[:category] - + conditions = "resource_id=:resource_id" values = {:resource_id => @snapshot.project_id} unless @category.blank? @@ -260,7 +262,7 @@ class ProjectController < ApplicationController snapshots_to_be_deleted = Snapshot.find(:all, :conditions => ["status='U' AND project_id=?", @snapshot.project_id]) unless snapshots_to_be_deleted.empty? conditions << " AND snapshot_id NOT IN (:sids)" - values[:sids] = snapshots_to_be_deleted.map {|s| s.id} + values[:sids] = snapshots_to_be_deleted.map { |s| s.id } end category_names=@categories.map { |cat| cat.name } @@ -342,7 +344,7 @@ class ProjectController < ApplicationController snapshot=Snapshot.find(params[:sid]) not_found("Snapshot not found") unless snapshot access_denied unless is_admin?(snapshot) - + # We update all the related snapshots to have the same version as the next snapshot next_snapshot = Snapshot.find(:first, :conditions => ['created_at>? and project_id=?', snapshot.created_at, snapshot.project_id], :order => 'created_at asc') snapshots = find_project_snapshots(snapshot.id) @@ -371,11 +373,11 @@ class ProjectController < ApplicationController else snapshots = find_project_snapshots(snapshot.id) snapshots.each do |s| - e = Event.new({:name => params[:event_name], - :category => EventCategory::KEY_OTHER, - :snapshot => s, - :resource_id => s.project_id, - :event_date => s.created_at}) + e = Event.new({:name => params[:event_name], + :category => EventCategory::KEY_OTHER, + :snapshot => s, + :resource_id => s.project_id, + :event_date => s.created_at}) e.save! end flash[:notice] = message('project_history.event_created', :params => params[:event_name]) @@ -425,7 +427,7 @@ class ProjectController < ApplicationController access_denied unless is_admin?(project) project end - + def find_project_snapshots(root_snapshot_id) snapshots = Snapshot.find(:all, :include => 'events', :conditions => ["(root_snapshot_id = ? OR id = ?) AND scope = 'PRJ'", root_snapshot_id, root_snapshot_id]) end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/settings_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/settings_controller.rb index 949775f5e82..50282117749 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/settings_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/settings_controller.rb @@ -21,80 +21,54 @@ class SettingsController < ApplicationController SECTION=Navigation::SECTION_CONFIGURATION - SPECIAL_CATEGORIES=['email', 'encryption', 'server_id'] + SPECIAL_CATEGORIES=%w(email encryption server_id) - verify :method => :post, :only => ['update'], :redirect_to => {:action => :index} + verify :method => :post, :only => %w(update), :redirect_to => {:action => :index} + before_filter :admin_required, :only => %w(index) def index - access_denied unless is_admin? - load_properties(nil) - @category ||= 'general' + load_properties() end def update - @project=nil - resource_id=nil - if params[:resource_id] - @project=Project.by_key(params[:resource_id]) - access_denied unless (@project && is_admin?(@project)) - resource_id=@project.id - else - access_denied unless is_admin? - end - is_global=(@project.nil?) - - load_properties(@project) - - @persisted_properties_per_key={} - if @category && @definitions_per_category[@category] - @definitions_per_category[@category].each do |property| - value=params[property.getKey()] - persisted_property = Property.find(:first, :conditions => {:prop_key=> property.key(), :resource_id => resource_id, :user_id => nil}) - - # update the property - if persisted_property - if value.empty? - Property.delete_all('prop_key' => property.key(), 'resource_id' => resource_id, 'user_id' => nil) - java_facade.setGlobalProperty(property.getKey(), nil) if is_global - elsif persisted_property.text_value != value.to_s - persisted_property.text_value = value.to_s - if persisted_property.save && is_global - java_facade.setGlobalProperty(property.getKey(), value.to_s) - end - @persisted_properties_per_key[persisted_property.key]=persisted_property - end - - # create the property - elsif value.present? - persisted_property=Property.new(:prop_key => property.key(), :text_value => value.to_s, :resource_id => resource_id) - if persisted_property.save && is_global - java_facade.setGlobalProperty(property.getKey(), value.to_s) - end - @persisted_properties_per_key[persisted_property.key]=persisted_property - end - end + resource_id = params[:resource_id] + @resource = Project.by_key(resource_id) if resource_id + + access_denied if (@resource && !is_admin?(@resource)) + access_denied if (@resource.nil? && !is_admin?) - params[:layout]='false' - render :partial => 'settings/properties' + load_properties() + + @definitions.map(&:key).each do |key| + value = params[key] + + if value.blank? + Property.clear(key, resource_id) + else + Property.set(key, value, resource_id) + end end + + render :partial => 'settings/properties' end private - def load_properties(project) - @category=params[:category] - @definitions_per_category={} - definitions = java_facade.getPropertyDefinitions() - definitions.getAll().select { |property_definition| - (project.nil? && property_definition.isGlobal()) || (project && project.module? && property_definition.isOnModule()) || (project && project.project? && property_definition.isOnProject()) - }.each do |property_definition| - category = definitions.getCategory(property_definition.getKey()) - @definitions_per_category[category]||=[] - @definitions_per_category[category]<<property_definition - end + def load_properties + @category = params[:category] || 'general' - SPECIAL_CATEGORIES.each do |category| - @definitions_per_category[category]=[] + if @resource.nil? + definitions_per_category = java_facade.propertyDefinitions.globalPropertiesByCategory + elsif @resource.project? + definitions_per_category = java_facade.propertyDefinitions.projectPropertiesByCategory + elsif @resource.module? + definitions_per_category = java_facade.propertyDefinitions.modulePropertiesByCategory end + + @categories = definitions_per_category.keys + SPECIAL_CATEGORIES + @definitions = definitions_per_category[@category] || [] + + not_found('category') unless @categories.include? @category end + end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/helpers/project_helper.rb b/sonar-server/src/main/webapp/WEB-INF/app/helpers/project_helper.rb index e4028760ddb..90ca275324d 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/helpers/project_helper.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/helpers/project_helper.rb @@ -19,6 +19,7 @@ # module ProjectHelper include ActionView::Helpers::UrlHelper + include SettingsHelper def formatted_value(measure, default='') measure ? measure.formatted_value : default diff --git a/sonar-server/src/main/webapp/WEB-INF/app/helpers/settings_helper.rb b/sonar-server/src/main/webapp/WEB-INF/app/helpers/settings_helper.rb new file mode 100644 index 00000000000..b6dfedd5fc5 --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/helpers/settings_helper.rb @@ -0,0 +1,56 @@ +# +# 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 +# +module SettingsHelper + def category_name(category) + message_or_default("property.category.#{category}", category) + end + + def property_name(property) + message_or_default("property.#{property.key()}.name", property.name()) + end + + def property_description(property) + message_or_default("property.#{property.key()}.description", property.description()) + end + + def property_value(property) + if property.multi_values + Property.values(property.key, @resource ? @resource.id : nil) + else + Property.value(property.key, @resource ? @resource.id : nil, '') + end + end + + # for backward-compatibility with properties that do not define the type TEXT + def property_type(property, value) + if property.getType().to_s=='STRING' && value && value.include?('\n') + return 'TEXT' + end + property.getType() + end + + def message_or_default(message_key, default) + message(message_key, :default => default) + end + + def by_name(categories) + categories.sort_by { |category| category_name(category) } + end +end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/property.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/property.rb index 3f8dfb72de6..39f617657ee 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/models/property.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/models/property.rb @@ -20,6 +20,10 @@ class Property < ActiveRecord::Base validates_presence_of :prop_key + named_scope :with_key, lambda { |value| {:conditions => {:prop_key, value}} } + named_scope :with_resource, lambda { |value| {:conditions => {:resource_id => value}} } + named_scope :with_user, lambda { |value| {:conditions => {:user_id => value}} } + def key prop_key end @@ -28,33 +32,48 @@ class Property < ActiveRecord::Base text_value end - def self.hash(resource_id=nil) - hash={} - Property.find(:all, :conditions => {'resource_id' => resource_id, 'user_id' => nil}).each do |prop| - hash[prop.key]=prop.value - end - hash + def self.hash(resource_id=nil, user_id=nil) + properties = Property.with_resource(resource_id).with_user(user_id) + + Hash[properties.map { |prop| [prop.key, prop.value] }] end - def self.value(key, resource_id=nil, default_value=nil) - prop=Property.find(:first, :conditions => {'prop_key' => key, 'resource_id' => resource_id, 'user_id' => nil}) - if prop - prop.text_value || default_value - else - default_value - end + def self.clear(key, resource_id=nil, user_id=nil) + all(key, resource_id, user_id).delete_all + Java::OrgSonarServerUi::JRubyFacade.getInstance().setGlobalProperty(key, nil) unless resource_id + end + + def self.by_key(key, resource_id=nil, user_id=nil) + all(key, resource_id, user_id).first + end + + def self.by_key_prefix(prefix) + Property.find(:all, :conditions => ['prop_key like ?', prefix + '%']) + end + + def self.value(key, resource_id=nil, default_value=nil, user_id=nil) + property = by_key(key, resource_id, user_id) + return default_value unless property + + property.text_value || default_value end - def self.values(key, resource_id=nil) - Property.find(:all, :conditions => {'prop_key' => key, 'resource_id' => resource_id, 'user_id' => nil}).collect { |p| p.text_value } + def self.values(key, resource_id=nil, user_id=nil) + value = value(key, resource_id, '', user_id) + values = value.split(',') + values.empty? ? [nil] : values.map { |v| v.gsub('%2C', ',') } end - def self.set(key, value, resource_id=nil) + def self.set(key, value, resource_id=nil, user_id=nil) + if value.kind_of? Array + value = value.map { |v| v.gsub(',', '%2C') }.join(',') + end + text_value = (value.nil? ? nil : value.to_s) - prop = Property.new(:prop_key => key, :text_value => text_value, :resource_id => resource_id) + prop = Property.new(:prop_key => key, :text_value => text_value, :resource_id => resource_id, :user_id => user_id) if prop.valid? Property.transaction do - Property.delete_all('prop_key' => key, 'resource_id' => resource_id, 'user_id' => nil) + Property.delete_all(:prop_key => key, :resource_id => resource_id, :user_id => user_id) prop.save end Java::OrgSonarServerUi::JRubyFacade.getInstance().setGlobalProperty(key, text_value) unless resource_id @@ -62,25 +81,8 @@ class Property < ActiveRecord::Base prop end - def self.clear(key, resource_id=nil) - Property.delete_all('prop_key' => key, 'resource_id' => resource_id, 'user_id' => nil) - Java::OrgSonarServerUi::JRubyFacade.getInstance().setGlobalProperty(key, nil) unless resource_id - end - - def self.by_key(key, resource_id=nil) - Property.find(:first, :conditions => {'prop_key' => key, 'resource_id' => resource_id, 'user_id' => nil}) - end - - def self.by_key_prefix(prefix) - Property.find(:all, :conditions => ["prop_key like ?", prefix + '%']) - end - - def self.update(key, value) - property = Property.find(:first, :conditions => {:prop_key => key, :resource_id => nil, :user_id => nil}); - property.text_value = value - property.save - Java::OrgSonarServerUi::JRubyFacade.getInstance().setGlobalProperty(key, value) - property + def self.update(key, value, resource_id=nil, user_id=nil) + set(key, value, resource_id, user_id) end def to_hash_json @@ -112,6 +114,10 @@ class Property < ActiveRecord::Base private + def self.all(key, resource_id=nil, user_id=nil) + Property.with_key(key).with_resource(resource_id).with_user(user_id) + end + def validate if java_definition validation_result=java_definition.validate(text_value) diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/settings/_multi_value.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/settings/_multi_value.html.erb new file mode 100644 index 00000000000..a571f937090 --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/settings/_multi_value.html.erb @@ -0,0 +1,5 @@ +<div class="multi_value"> + <%= render "settings/type_#{property_type(property, value)}", :property => property, :value => value -%> + <a href="#" class="delete"></a> + <br/> +</div> diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/settings/_properties.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/settings/_properties.html.erb index e77b7583790..3e9602d4820 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/settings/_properties.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/settings/_properties.html.erb @@ -1,87 +1,67 @@ -<% if @category && @definitions_per_category[@category] - category_name = message("property.category.#{@category}", :default => @category) - if SettingsController::SPECIAL_CATEGORIES.include?(@category) -%> - <%= render :partial => 'special', :locals => {:url => url_for(:controller => "#{@category}_configuration")} -%> - <% - elsif !@definitions_per_category[@category].empty? - %> - <% form_remote_tag :url => {:controller => 'settings', :action => 'update', :category => @category, :resource_id => @project ? @project.id : nil}, - :method => :post, - :before => "$('submit_settings').hide();$('loading_settings').show()", - :update => 'properties' do -%> +<% if SettingsController::SPECIAL_CATEGORIES.include?(@category) -%> + <%= render 'special', :url => url_for(:controller => "#{@category}_configuration") -%> +<% else -%> + <% form_remote_tag :url => {:controller => 'settings', :action => 'update', :category => @category, :resource_id => @resource ? @resource.id : nil}, + :method => :post, + :before => "$('submit_settings').hide();$('loading_settings').show();", + :update => 'properties', + :script => false do -%> - <table class="data marginbottom10" style="margin: 10px"> - <thead> - <tr> - <th> - <span><%= h(category_name) -%></span> - </th> - </tr> - </thead> - <tbody> - <% - if @definitions_per_category[@category] - @definitions_per_category[@category].each do |property| - value = nil - - # set when form has been submitted but some errors have been raised - if @persisted_properties_per_key - p = @persisted_properties_per_key[property.key] - if p - value = p.text_value - end - end + <table class="data marginbottom10" style="margin: 10px;"> + <thead> + <tr> + <th><%= h category_name(@category) -%></th> + </tr> + </thead> + <tbody> + <% @definitions.each do |property| -%> + <tr class="<%= cycle('even', 'odd', :name => 'properties') -%>"> + <td style="padding: 10px" id="block_<%= property.key -%>"> + <h3> + <div><%= property_name(property) -%></div> + <div class="note"><%= property.key -%></div> + </h3> + <% desc=property_description(property) -%> + <% unless desc.blank? %> + <p class="marginbottom10"><%= desc -%></p> + <% end -%> + <% value = property_value(property) -%> + <% if property.multi_values -%> + <% value.each do |sub_value| -%> + <%= render "settings/multi_value", :property => property, :value => sub_value -%> + <% end -%> + <div class="template" style="display:none;"> + <%= render "settings/multi_value", :property => property, :value => nil -%> + </div> + <a href="#" class="add"><%= message('settings.add') -%></a> + <% else -%> + <%= render "settings/type_#{property_type(property, value)}", :property => property, :value => value -%> + <% end -%> - # if fresh form or no error, get the current value - value = Property.value(property.getKey(), (@project ? @project.id : nil), '') unless value + <% default_prop_value = (@resource ? Property.value(property.key, nil, property.defaultValue) : property.defaultValue) -%> + <% unless default_prop_value.blank? %> + <p class="note">Default: <%= property.type.to_s=='PASSWORD' ? '********' : h(default_prop_value) -%></p> + <% end -%> + </td> + </tr> + <% end -%> + </tbody> + </table> + <div style="padding-left: 16px;"> + <%= submit_tag(message('settings.save_category', :params => [category_name(@category)]), :id => 'submit_settings') -%> + <img src="<%= ApplicationController.root_context -%>/images/loading.gif" id="loading_settings" style="display:none;"> + </div> + <% end -%> +<% end -%> - # for backward-compatibility with properties that do not define the type TEXT - property_type = property.getType() - if property_type.to_s=='STRING' && value.include?("\n") - property_type = 'TEXT' - end +<script type="text/javascript"> + $j('.delete').live('click', function () { + $j(this).parent('.multi_value').remove(); + }); - %> - <tr class="<%= cycle('even', 'odd', :name => 'properties') -%>"> - <td style="padding: 10px" id="block_<%= property.getKey() -%>"> - <h3> - <%= message("property.#{property.key()}.name", :default => property.name()) -%> - <br/><span class="note"><%= property.getKey() -%></span> - </h3> - <% - desc=message("property.#{property.key()}.description", :default => property.description()) - if desc.present? %> - <p class="marginbottom10"><%= desc -%></p> - <% end %> - <div><%= render :partial => "settings/type_#{property_type}", :locals => {:property => property, :value => value} -%></div> - <% - if p && !p.valid? - %> - <div class="error"><%= p.validation_error_message -%></div> - <% - end - %> - <p> - <% - default_prop_value = (@project ? Property.value(property.key(), nil, property.defaultValue()) : property.defaultValue()) - unless default_prop_value.blank? %> - <span class="note">Default : <%= property.getType().to_s=='PASSWORD' ? '********' : h(default_prop_value) -%></span> - <% end %> - </p> - </td> - </tr> - <% end - end - %> - </tbody> - </table> - <div style="padding-left: 16px"> - <%= submit_tag(message('settings.save_category', :params => [category_name]), :id => 'submit_settings') -%> - <img src="<%= ApplicationController.root_context -%>/images/loading.gif" id="loading_settings" style="display:none"> - </div> - <% end %> - <% end - end - %> + $j('.add').live('click', function () { + var template = $j(this).siblings('.template'); + template.before(template.html()); + }); +</script>
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/settings/_settings.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/settings/_settings.html.erb index b9975d9d0ab..3411c37143a 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/settings/_settings.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/settings/_settings.html.erb @@ -1,28 +1,33 @@ -<style type="text/css"> - #plugins .plugin { - padding: 5px; - border: 1px solid #ddd; - background-color: #fff; - } +<h1 class="marginbottom10"><%= message('settings.page') -%></h1> - #plugins .plugin h2 { - margin-left: 10px; - font-size: 122%; - color: #333; - } +<table width="100%"> + <tr> + <td width="1%" nowrap class="column first"> + <table class="data selector"> + <thead> + <tr> + <th><%= message('category') -%></th> + </tr> + </thead> + <tbody> + <% by_name(@categories).each do |category| -%> + <tr id="select_<%= category -%>" class="select <%= cycle('even', 'odd', :name => 'category') -%> <%= 'selected' if @category==category -%>"> + <td><%= link_to category_name(category), :category => category -%></td> + </tr> + <% end -%> + </tbody> + </table> + <br/> + </td> - #plugins .plugin h3 { - margin-left: 5px; - } + <td class="column"> + <div id="properties"> + <%= render 'settings/properties' -%> + </div> + </td> + </tr> +</table> - #plugins .plugin p { - padding: 5px 5px; - } - - #plugins .plugin img { - padding: 5px 0 0 5px; - } -</style> <script type="text/javascript"> function enlargeTextInput(propertyKey) { var eltId = 'input_' + propertyKey; @@ -31,40 +36,3 @@ $(eltId).parentNode.replace(textArea); } </script> -<div id="plugins"> - <h1 class="marginbottom10"><%= message('settings.page') -%></h1> - <table width="100%"> - <tr> - <td width="1%" nowrap class="column first"> - <table class="data selector"> - <thead> - <tr> - <th> - <span>Category</span> - </th> - </tr> - </thead> - <tbody> - <% - @definitions_per_category.keys.sort_by { |category| message("property.category.#{category}", :default => category).upcase }.each do |category| - if !@definitions_per_category[category].empty? || SettingsController::SPECIAL_CATEGORIES.include?(category) - %> - <tr class="select <%= cycle('even', 'odd', :name => 'category') -%> <%= 'selected' if @category==category -%>" id="select_<%= category -%>"> - <td><%= link_to message("property.category.#{category}", :default => category), :overwrite_params => {:category => category} -%></td> - </tr> - <% end - end - %> - </tbody> - </table> - <br/> - </td> - - <td class="column"> - <div id="properties" style="width:99%"> - <%= render :partial => 'settings/properties' -%> - </div> - </td> - </tr> - </table> -</div> diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/settings/_sidebar.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/settings/_sidebar.html.erb deleted file mode 100644 index e69de29bb2d..00000000000 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/settings/_sidebar.html.erb +++ /dev/null diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/settings/_type_STRING.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/settings/_type_STRING.html.erb index b4c3b451f4d..7292d327860 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/settings/_type_STRING.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/settings/_type_STRING.html.erb @@ -1,2 +1,2 @@ -<input type="text" name="<%= h property.getKey() -%>" value="<%= h value if value -%>" size="50" id="input_<%= h property.getKey() -%>"/> -<%= link_to_function(image_tag('zoom.png'), "enlargeTextInput('#{property.getKey()}')", :class => 'nolink') -%>
\ No newline at end of file +<input type="text" name="<%= h property.key -%>[]" value="<%= h value if value -%>" size="50" id="input_<%= h property.key -%>"/> +<%= link_to_function(image_tag('zoom.png'), "enlargeTextInput('#{property.key}')", :class => 'nolink') -%>
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/settings/index.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/settings/index.html.erb index 81fa7362a09..d2c6ebcae2c 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/settings/index.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/settings/index.html.erb @@ -1 +1 @@ -<%= render :partial => 'settings', :locals => {:project=>nil} %>
\ No newline at end of file +<%= render 'settings', :project => nil %>
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/stylesheets/style.css b/sonar-server/src/main/webapp/stylesheets/style.css index 74584a1093b..ff58b01e301 100644 --- a/sonar-server/src/main/webapp/stylesheets/style.css +++ b/sonar-server/src/main/webapp/stylesheets/style.css @@ -2087,6 +2087,11 @@ table.nowrap td, td.nowrap, th.nowrap { padding: 2px 0 2px 20px; } +.delete { + background: url("../images/cross.png") no-repeat scroll left 50% transparent; + padding: 2px 0 2px 20px; +} + .restore { display: block; background: url("../images/restore.gif") no-repeat scroll left 50% transparent; |