diff options
Diffstat (limited to 'sonar-server/src/main/webapp/WEB-INF')
16 files changed, 408 insertions, 225 deletions
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/application_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/application_controller.rb index 8636de40e54..e125aaefe2d 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/application_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/application_controller.rb @@ -125,6 +125,23 @@ class ApplicationController < ActionController::Base raise Errors::AccessDenied end + # since 3.3 + def require_parameters(*keys) + keys.each do |key| + bad_request("Missing parameter: #{key}") if params[key].blank? + end + end + + # since 3.3 + def verify_post_request + bad_request('Not a POST request') unless request.post? + end + + # since 3.3 + def verify_ajax_request + bad_request('Not an AJAX request') unless request.xhr? + end + def render_not_found(error) render :file => "#{Rails.public_path}/404.html", :status => 404 end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/profiles_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/profiles_controller.rb index d380dbff837..50fbf55c26f 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/profiles_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/profiles_controller.rb @@ -20,38 +20,37 @@ class ProfilesController < ApplicationController SECTION=Navigation::SECTION_CONFIGURATION - # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html) - verify :method => :post, :only => ['create', 'delete', 'copy', 'set_as_default', 'restore', 'set_projects', 'rename', 'change_parent'], :redirect_to => {:action => 'index'} - # the backup action is allow to non-admin users : see http://jira.codehaus.org/browse/SONAR-2039 before_filter :admin_required, :only => ['create', 'delete', 'set_as_default', 'copy', 'restore', 'change_parent', 'set_projects', 'rename_form', 'rename'] # GET /profiles/index def index - @profiles = Profile.find(:all, :conditions => ['enabled=?', true], :order => 'name') + @profiles = Profile.find(:all, :order => 'name') end # GET /profiles/show/<id> def show + require_parameters 'id' @profile = Profile.find(params[:id]) end # GET /profiles/create_form?language=<language> def create_form - language = params[:language] - bad_request 'Missing parameter: language' if language.blank? - profile = Profile.new(:language => language) - render :partial => 'profiles/create_form', :locals => {:language_key => language} + require_parameters 'language' + render :partial => 'profiles/create_form', :locals => {:language_key => params[:language]} end # POST /profiles/create?name=<profile name>&language=<language>&[backup=<file>] def create + verify_post_request + require_parameters 'language' + profile_name=params[:name] language=params[:language] - profile = Profile.create(:name => profile_name, :language => language, :default_profile => false, :enabled => true) + profile = Profile.create(:name => profile_name, :language => language, :default_profile => false) ok = profile.errors.empty? if ok && params[:backup] params[:backup].each_pair do |importer_key, file| @@ -75,9 +74,12 @@ class ProfilesController < ApplicationController # POST /profiles/delete/<id> def delete + verify_post_request + require_parameters 'id' + @profile = Profile.find(params[:id]) if @profile && @profile.deletable? - java_facade.deleteProfile(@profile.id) + @profile.destroy end redirect_to(:controller => 'profiles', :action => 'index') end @@ -85,40 +87,50 @@ class ProfilesController < ApplicationController # POST /profiles/set_as_default/<id> def set_as_default + verify_post_request + require_parameters 'id' + profile = Profile.find(params[:id]) profile.set_as_default - flash[:notice]=message('quality_profiles.default_profile_is_x', :params => profile.name) + #TODO remove l10n key: flash[:notice]=message('quality_profiles.default_profile_is_x', :params => profile.name) redirect_to :action => 'index' end # GET /profiles/copy_form/<profile id> def copy_form + require_parameters 'id' @profile = Profile.find(params[:id]) render :partial => 'profiles/copy_form' end # POST /profiles/copy/<id>?name=<name of new profile> def copy - render :text => 'Not an ajax request', :status => '400' unless request.xhr? + verify_post_request + verify_ajax_request + require_parameters 'id' @profile = Profile.find(params[:id]) name = params['name'] - validation_errors = @profile.validate_copy(name) - if validation_errors.empty? + target_profile=Profile.new(:name => name, :language => @profile.language, :provided => false, :default_profile => false) + if target_profile.valid? java_facade.copyProfile(@profile.id, name) flash[:notice]= message('quality_profiles.profile_x_not_activated', :params => name) render :text => 'ok', :status => 200 else - @error = validation_errors.full_messages.first + @errors = [] + target_profile.errors.each{|attr,msg| @errors<<msg} render :partial => 'profiles/copy_form', :status => 400 end end - # POST /profiles/backup/<id> + # POST /profiles/backup?id=<profile id> def backup + verify_post_request + require_parameters 'id' + profile = Profile.find(params[:id]) xml = java_facade.backupProfile(profile.id) filename=profile.name.gsub(' ', '_') @@ -129,11 +141,13 @@ class ProfilesController < ApplicationController # Modal window to restore profile backup # GET /profiles/restore_form/<profile id> def restore_form + verify_ajax_request render :partial => 'profiles/restore_form' end # POST /profiles/restore?backup=<file> def restore + verify_post_request if params[:backup].blank? flash[:warning]=message('quality_profiles.please_upload_backup_file') else @@ -148,7 +162,7 @@ class ProfilesController < ApplicationController def export language = params[:language] if (params[:name].blank?) - profile = Profile.find_active_profile_by_language(language) + profile = Profile.by_default(language) else profile = Profile.find_by_name_and_language(CGI::unescape(params[:name]), language) end @@ -165,24 +179,18 @@ class ProfilesController < ApplicationController end end - # - # # GET /profiles/inheritance?id=<profile id> - # - # def inheritance + require_parameters 'id' @profile = Profile.find(params[:id]) - profiles=Profile.find(:all, :conditions => ['language=? and id<>? and (parent_name is null or parent_name<>?) and enabled=?', @profile.language, @profile.id, @profile.name, true], :order => 'name') + profiles=Profile.find(:all, :conditions => ['language=? and id<>? and (parent_name is null or parent_name<>?)', @profile.language, @profile.id, @profile.name], :order => 'name') @select_parent = [[message('none'), nil]] + profiles.collect { |profile| [profile.name, profile.name] } end - # - # # GET /profiles/changelog?id=<profile id> - # - # def changelog + require_parameters 'id' @profile = Profile.find(params[:id]) versions = ActiveRuleChange.find(:all, :select => 'profile_version, MAX(change_date) AS change_date', :conditions => ['profile_id=?', @profile.id], :group => 'profile_version') @@ -210,12 +218,11 @@ class ProfilesController < ApplicationController end - # - # # POST /profiles/change_parent?id=<profile id>&parent_name=<parent profile name> - # - # def change_parent + verify_post_request + require_parameters 'id' + id = params[:id].to_i parent_name = params[:parent_name] if parent_name.blank? @@ -234,6 +241,7 @@ class ProfilesController < ApplicationController # # def permalinks + require_parameters 'id' @profile = Profile.find(params[:id]) end @@ -244,62 +252,68 @@ class ProfilesController < ApplicationController # # def projects + require_parameters 'id' @profile = Profile.find(params[:id]) - @available_projects=Project.find(:all, - :include => ['profile', 'snapshots'], - :conditions => ['projects.qualifier=? AND projects.scope=? AND snapshots.islast=?', Project::QUALIFIER_PROJECT, Project::SCOPE_SET, true], - :order => 'projects.name asc') - @available_projects-=@profile.projects end - # - # - # POST /profiles/set_projects/<id>?projects=<project ids> - # - # - def set_projects - @profile = Profile.find(params[:id]) - @profile.projects.clear + # POST /profiles/add_project?id=<profile id>&project_id=<project id> + def add_project + verify_post_request + require_parameters 'id', 'project_id' + admin_required + + profile=Profile.find(params[:id]) + bad_request('Unknown profile') unless profile + project=Project.find(params[:project_id]) + bad_request('Unknown project') unless project - projects=Project.find(params[:projects] || []) - @profile.projects=projects - flash[:notice]=message('quality_profiles.profile_x_associated_to_x_projects', :params => [@profile.name, projects.size]) - redirect_to :action => 'projects', :id => @profile.id + profile.add_project_id(project.id) + redirect_to :action => 'projects', :id => profile.id end + # POST /profiles/remove_project?id=<profile id>&project_id=<project id> + def remove_project + verify_post_request + require_parameters 'id', 'project_id' + admin_required + + profile=Profile.find(params[:id]) + bad_request('Unknown profile') unless profile + + Profile.reset_default_profile_for_project_id(profile.language, params[:project_id]) + redirect_to :action => 'projects', :id => profile.id + end + + # POST /profiles/remove_projects?id=<profile id> + def remove_projects + verify_post_request + require_parameters 'id' + admin_required + + profile=Profile.find(params[:id]) + bad_request('Unknown profile') unless profile + + profile.remove_projects + redirect_to :action => 'projects', :id => profile.id + end # GET /profiles/rename_form?id=<id> def rename_form + require_parameters 'id' @profile = Profile.find(params[:id]) render :partial => 'profiles/rename_form' end - # - # # POST /profiles/rename?id=<id>&name=<new name> - # - # def rename - render :text => 'Not an ajax request', :status => '400' unless request.xhr? + verify_post_request + verify_ajax_request + require_parameters 'id' @profile = Profile.find(params[:id]) - name = params[:name] - success=false - if name.blank? - @error=message('quality_profiles.profile_name_cant_be_blank') - else - existing=Profile.find(:first, :conditions => {:name => name, :language => @profile.language, :enabled => true}) - if existing - @error=message('quality_profiles.already_exists') - elsif !@profile.provided? - java_facade.renameProfile(@profile.id, name) - success=true - end - end - - if success + if @profile.rename(params[:name]).errors.empty? render :text => 'ok', :status => 200 else render :partial => 'profiles/rename_form', :status => 400 @@ -307,13 +321,9 @@ class ProfilesController < ApplicationController end - # - # # GET /profiles/compare?id1=<profile1 id>&id2=<profile2 id> - # - # def compare - @profiles = Profile.find(:all, :conditions => ['enabled=?', true], :order => 'language asc, name') + @profiles = Profile.find(:all, :order => 'language asc, name') if params[:id1].present? && params[:id2].present? @profile1 = Profile.find(params[:id1]) @profile2 = Profile.find(params[:id2]) 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 a993d5331ec..5e59296c6e3 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], :redirect_to => {:action => :index} verify :method => :delete, :only => [:delete], :redirect_to => {:action => :index} @@ -75,25 +75,29 @@ class ProjectController < ApplicationController redirect_to :action => 'deletion', :id => params[:id] end - def quality_profile + # GET /project/profile?id=<project id> + def profile + require_parameters :id @project = get_current_project(params[:id]) - @profiles = Profile.find(:all, :conditions => {:language => @project.language, :enabled => true}) end - def update_quality_profile + # POST /project/set_profile?id=<project id>&language=<language>[&profile_id=<profile id>] + def set_profile + require_parameters :id, :language + verify_post_request + + language=params[:language] 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 - project.profile = selected_profile - project.save! - flash[:notice] = message('project_quality_profile.profile_successfully_updated') + if params[:profile_id].blank? + Profile.reset_default_profile_for_project_id(language, project.id) else - 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) + profile = Profile.find(params[:profile_id]) + bad_request('Bad language') if profile.language!=language + profile.add_project_id(project.id) end - redirect_to :action => 'quality_profile', :id => project.id + redirect_to :action => 'profile', :id => project.id end def key 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 39b9ac0f3ab..8720d718e20 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 @@ -721,7 +721,7 @@ module ApplicationHelper end # - # Creates a button linked to a POST action. A confirmation popup is opened when user clicks on the button. + # Creates a link linked to a POST action. A confirmation popup is opened when user clicks on the button. # ==== Options # * <tt>:id</tt> - HTML ID of the button # * <tt>:class</tt> - Additional CSS class, generally 'red-button' for deletions @@ -731,7 +731,7 @@ module ApplicationHelper # * <tt>:message_params</tt> - # * <tt>:width</tt> - width in pixels # - def button_to_action(label, post_url, options={}) + def link_to_action(label, post_url, options={}) clazz = options[:class] id = "id='#{options[:id]}'" if options[:id] title_key = options[:title_key] @@ -750,6 +750,6 @@ module ApplicationHelper url += "&bk=#{button_key}" end - "<a href='#{url}' modal-width='#{width}' class='open-modal button #{clazz}' #{id}>#{h label}</a>" + "<a href='#{url}' modal-width='#{width}' class='open-modal #{clazz}' #{id}>#{h label}</a>" end end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/api/utils.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/api/utils.rb index ddf214b88e2..81e74632ca9 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/models/api/utils.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/models/api/utils.rb @@ -169,4 +169,8 @@ class Api::Utils def self.java_facade Java::OrgSonarServerUi::JRubyFacade.getInstance() end + + def self.languages + java_facade.getLanguages() + end end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/profile.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/profile.rb index 079645ff6c6..a9bb3d3a20e 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/models/profile.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/models/profile.rb @@ -22,13 +22,21 @@ class Profile < ActiveRecord::Base has_many :alerts, :dependent => :delete_all has_many :active_rules, :class_name => 'ActiveRule', :foreign_key => 'profile_id', :dependent => :destroy, :include => ['rule'] - has_many :projects, :order => 'name asc' - has_many :active_rules_with_params, :class_name => 'ActiveRule', :foreign_key => 'profile_id', - :include => ['active_rule_parameters', 'active_rule_note'] + has_many :active_rules_with_params, :class_name => 'ActiveRule', :foreign_key => 'profile_id', :include => ['active_rule_parameters', 'active_rule_note'] + has_many :projects, :class_name => 'Project', :finder_sql => %q( + select prj.* from projects prj, properties prop where prj.id=prop.resource_id and prop.resource_id is not null and prop.prop_key='sonar.profile.#{language}' and prop.text_value='#{name}' + ) + has_many :changes, :class_name => 'ActiveRuleChange', :dependent => :destroy + has_many :children, :class_name => 'Profile', :finder_sql => %q( + select c.* from rules_profiles c where c.parent_name='#{name}' and c.language='#{language}' + ) validates_uniqueness_of :name, :scope => :language, :case_sensitive => false, :message => Api::Utils.message('quality_profiles.already_exists') validates_presence_of :name, :message => Api::Utils.message('quality_profiles.please_type_profile_name') + MAX_NAME_LENGTH = 100 + validates_length_of :name, :maximum => MAX_NAME_LENGTH, :message => Api::Utils.message('name_too_long_x', :params => [MAX_NAME_LENGTH]) + # The warnings that are set on this record, equivalent to normal ActiveRecord errors but does not prevent # the record from saving. def warnings @@ -36,7 +44,7 @@ class Profile < ActiveRecord::Base end def warnings? - not warnings.empty? + !warnings.empty? end def notices @@ -59,34 +67,16 @@ class Profile < ActiveRecord::Base provided end - def validate_copy(name) - new_rule_profile = Profile.new(:name => name, :provided => false, :default_profile => false, :language => language) - new_rule_profile.valid? - new_rule_profile.errors - end - - def self.find_by_name_and_language(name, language) - Profile.find(:first, :conditions => {:name => name, :language => language, :enabled => true}) - end - - def self.find_active_profile_by_language(language) - Profile.find(:first, :conditions => {:default_profile => true, :language => language, :enabled => true}) - end - - def self.default_profile - Profile.find(:first, :conditions => {:default_profile => true, :enabled => true}) - end - def set_as_default - default_profile=nil - Profile.find(:all, :conditions => {:language => language, :enabled => true}).each do |profile| - if profile.id==id - profile.default_profile=true - default_profile=profile - else - profile.default_profile=false + Profile.transaction do + Profile.find(:all, :conditions => {:language => language}).each do |profile| + if profile.id==id + profile.default_profile=true + else + profile.default_profile=false + end + profile.save end - profile.save end self end @@ -97,7 +87,7 @@ class Profile < ActiveRecord::Base def self.options_for_select array=[] - Profile.find(:all, :conditions => {:enabled => true}, :order => 'name').each do |profile| + Profile.find(:all, :order => 'name').each do |profile| label = profile.name label = label + ' (active)' if profile.default_profile? array<<[label, profile.id] @@ -123,9 +113,9 @@ class Profile < ActiveRecord::Base def count_overriding_rules @count_overriding_rules||= - begin - active_rules.count(:conditions => ['inheritance=?', 'OVERRIDES']) - end + begin + active_rules.count(:conditions => ['inheritance=?', 'OVERRIDES']) + end end def inherited? @@ -134,13 +124,13 @@ class Profile < ActiveRecord::Base def parent @parent||= - begin - if parent_name.present? - Profile.find(:first, :conditions => ['language=? and name=? and enabled=?', language, parent_name, true]) - else - nil - end + begin + if parent_name.present? + Profile.find(:first, :conditions => ['language=? and name=?', language, parent_name]) + else + nil end + end end def count_active_rules @@ -149,21 +139,14 @@ class Profile < ActiveRecord::Base def ancestors @ancestors ||= - begin - array=[] - if parent - array<<parent - array.concat(parent.ancestors) - end - array - end - end - - def children - @children ||= - begin - Profile.find(:all, :conditions => ['language=? and parent_name=? and enabled=?', language, name, true], :order => 'name') + begin + array=[] + if parent + array<<parent + array.concat(parent.ancestors) end + array + end end def import_configuration(importer_key, file) @@ -178,4 +161,60 @@ class Profile < ActiveRecord::Base notices.add_to_base msg end end + + def before_destroy + Property.clear_for_resources("sonar.profile.#{language}", name) + #TODO clear global property sonar.profile.#{language} with value #{name} + end + + def rename(new_name) + old_name=self.name + Profile.transaction do + children_to_be_renamed=children() + self.name=new_name + if save + children_to_be_renamed.each do |child| + child.parent_name=new_name + child.save + end + Property.update_all("text_value='#{new_name}'", ['prop_key=? and text_value=?', "sonar.profile.#{language}", old_name]) + end + end + self + end + + def add_project_id(project_id) + Property.set("sonar.profile.#{language}", name, project_id) + end + + def remove_projects + Property.clear_for_resources("sonar.profile.#{language}", name) + end + + def self.reset_default_profile_for_project_id(lang, project_id) + Property.clear("sonar.profile.#{lang}", project_id) + end + + def self.by_project_id(language, project_id, returns_default_if_nil=false) + profile_name=Property.value("sonar.profile.#{language}", project_id) + profile = (profile_name.present? ? Profile.find_by_name_and_language(profile_name, language) : nil) + + if !profile && returns_default_if_nil + profile = by_default(language) + end + profile + end + + def self.by_default(language) + Profile.find(:first, :conditions => {:default_profile => true, :language => language}) + end + + # Results are NOT sorted + def self.all_by_language(language) + Profile.find(:all, :conditions => {:language => language}) + end + + def self.find_by_name_and_language(name, language) + Profile.find(:first, :conditions => {:name => name, :language => language}) + end end
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/project.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/project.rb index 07e3a251282..4acf953c17c 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/models/project.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/models/project.rb @@ -25,7 +25,6 @@ class Project < ActiveRecord::Base has_many :processed_snapshots, :class_name => 'Snapshot', :conditions => "status='#{Snapshot::STATUS_PROCESSED}' AND qualifier<>'LIB'", :order => 'created_at asc' has_many :events, :foreign_key => 'resource_id', :order => 'event_date DESC' has_many :project_links, :dependent => :delete_all, :order => 'link_type' - belongs_to :profile, :class_name => 'Profile', :foreign_key => 'profile_id' has_many :user_roles, :foreign_key => 'resource_id' has_many :group_roles, :foreign_key => 'resource_id' has_many :manual_measures, :foreign_key => 'resource_id' @@ -182,6 +181,10 @@ class Project < ActiveRecord::Base last_snapshot ? last_snapshot.path_name : nil end + def profile(lang, returns_default_if_nil=false) + Profile.by_project_id(lang, id, returns_default_if_nil) + end + private def create_chart_measures(results, date_column_name, value_column_name) 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 976fdf7480a..6371b51242d 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 @@ -21,9 +21,11 @@ class Property < ActiveRecord::Base validates_presence_of :prop_key named_scope :with_key, lambda { |value| {:conditions => {:prop_key, value}} } + named_scope :with_value, lambda { |value| {:conditions => {:text_value, value}} } named_scope :with_resource, lambda { |value| {:conditions => {:resource_id => value}} } named_scope :with_user, lambda { |value| {:conditions => {:user_id => value}} } - named_scope :on_resource, :conditions => ['resource_id is not ?', nil] + named_scope :with_resources, :conditions => 'resource_id is not null' + named_scope :with_users, :conditions => 'user_id is not null' def key prop_key @@ -47,6 +49,18 @@ class Property < ActiveRecord::Base end end + def self.clear_for_resources(key, value=nil) + scope=Property.with_resources().with_key(key) + if value + scope.with_value(value) + end + scope.delete_all + end + + def self.clear_for_users(key) + Property.with_users().with_key(key).delete_all + end + def self.by_key(key, resource_id=nil, user_id=nil) all(key, resource_id, user_id).first end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/layouts/_layout.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/layouts/_layout.html.erb index 9788893ab96..96d831919b5 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/layouts/_layout.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/layouts/_layout.html.erb @@ -89,8 +89,8 @@ <% if has_role?(:admin, @project) %> <li class="h2"><%= message('sidebar.project_settings') -%></li> <% if (@project.project?) %> - <li class="<%= 'selected' if request.request_uri.include?('/project/quality_profile') -%>"> - <a href="<%= ApplicationController.root_context -%>/project/quality_profile/<%= @project.id -%>"><%= message('project_quality_profile.page') -%></a></li> + <li class="<%= 'selected' if request.request_uri.include?('/project/profile') -%>"> + <a href="<%= ApplicationController.root_context -%>/project/profile/<%= @project.id -%>"><%= message('project_quality_profile.page') -%></a></li> <% end %> <li class="<%= 'selected' if request.request_uri.include?('/manual_measures') -%>"> <a href="<%= ApplicationController.root_context -%>/manual_measures/index/<%= @project.id -%>"><%= message('manual_measures.page') -%></a></li> diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/_copy_form.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/_copy_form.html.erb index bff1d8c7bfc..535ea549a10 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/_copy_form.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/_copy_form.html.erb @@ -2,14 +2,18 @@ <input type="hidden" name="id" value="<%= @profile.id -%>"/> <fieldset> <div class="form-head"> - <h2>Copy Profile: <%= h @profile.name -%></h2> + <h2> <%= message('quality_profiles.copy_x_title', :params => [h @profile.name]) -%></h2> </div> <div class="form-body"> - <% if @error %> - <p class="error"><%= h @error -%></p> - <% end %> + <% if @errors + @errors.each do |error| + %> + <p class="error"><%= h error -%></p> + <% end + end + %> <div class="form-field"> - <label for="name">New name <em>*</em></label> + <label for="name"><%= message 'quality_profiles.copy_new_name' -%> <em>*</em></label> <input id="copy-name" name="name" type="text" size="50" maxlength="100"/> </div> </div> diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/_rename_form.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/_rename_form.html.erb index 4da833e138d..b7c11aa4ac7 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/_rename_form.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/_rename_form.html.erb @@ -3,12 +3,12 @@ <fieldset> <div class="form-head"> - <h2>Rename Profile: <%= h @profile.name -%></h2> + <h2>Rename Profile: <%= h @profile.name_was -%></h2> </div> <div class="form-body"> - <% if @error %> - <p class="error"><%= h @error -%></p> + <% @profile.errors.each do |attr, msg| %> + <p class="error"><%= h msg -%></p> <% end %> <div class="form-field"> diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/index.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/index.html.erb index 201a7718682..50efc517ad0 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/index.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/index.html.erb @@ -49,7 +49,7 @@ </td> <td align="right"> - <span id="activated_rules_<%= u profile.key -%>"><%= profile.count_active_rules -%></span> + <span id="activated_rules_<%= u profile.key -%>"><%= profile.active_rules.count -%></span> </td> <td align="right"><span id="alerts_<%= u profile.key -%>"><%= profile.alerts.size -%></span></td> @@ -62,8 +62,9 @@ <td align="right"> <% if !profile.default_profile? && administrator? %> - <%= button_to_action message('set_as_default'), "profiles/set_as_default?id=#{profile.id}", + <%= link_to_action message('set_as_default'), "profiles/set_as_default?id=#{profile.id}", :id => "activate_#{profile.key.parameterize}", + :class => 'button', :title_key => 'set_as_default', :message_key => 'quality_profiles.are_you_sure_want_x_profile_as_default', :message_params => [profile.name] -%> @@ -96,8 +97,8 @@ <td> <% if profile.deletable? %> - <%= button_to_action message('delete'), "profiles/delete/#{profile.id}", - :class => 'red-button', + <%= link_to_action message('delete'), "profiles/delete/#{profile.id}", + :class => 'button red-button', :id => "delete_#{profile.key.parameterize}", :button_key => 'delete', :title_key => 'quality_profiles.delete_confirm_title', diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/projects.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/projects.html.erb index 8a155a8adbd..df77976eb84 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/projects.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/projects.html.erb @@ -1,54 +1,79 @@ -<h1 class="marginbottom10"><%= link_to message('quality_profiles.quality_profiles'), :controller => 'profiles', :action => 'index' -%> / <%= h @profile.language -%> / <%= h @profile.name %></h1> -<%= render :partial => 'profiles/tabs', :locals => {:selected_tab=>'Projects'} %> +<h1 class="marginbottom10"><%= link_to message('quality_profiles.quality_profiles'), :controller => 'profiles', :action => 'index' -%> / <%= h @profile.language -%> + / <%= h @profile.name %></h1> +<%= render :partial => 'profiles/tabs', :locals => {:selected_tab => 'Projects'} %> <div class="tabs-panel"> -<% if is_admin? %> -<form action="<%= url_for :action => 'set_projects' -%>" method="post" id="select_projects_form"> - <input type="hidden" name="id" value="<%= @profile.id -%>"/> -<table> - <tr> - <td style="padding: 5px 0" valign="top"> - <h3><%= message('quality_profiles.available_projects') -%></h3> - <select name="from" id="from" size="10" style="max-width:380px;margin-top: 5px" multiple="multiple"> - <% @available_projects.each do |project| %> - <option value="<%= project.id -%>"><%= project.name %><%= " (#{project.profile.name})" if project.profile %></option> + <% if is_admin? %> + <form method="POST" action="<%= ApplicationController.root_context -%>/profiles/add_project" id="add_project_form"> + <input type="hidden" name="id" value="<%= @profile.id -%>"/> + + Add project: <%= resource_select_tag 'project_id', { + :qualifiers => ['TRK'], + :width => '400px', + :html_id => "select-project", + } -%> + <script>$j('#select-project').on("change", function (e) { + $j(this).select2("disable"); + $j('#add_project_form').submit(); + })</script> + </form> + + <% unless @profile.projects.empty? %> + <table class="data"> + <thead> + <tr> + <th></th> + <th></th> + </tr> + </thead> + <tbody> + <% @profile.projects.each do |project| %> + <tr class="<%= cycle('even', 'odd') -%>"> + <td class="thin"> + <%= link_to_action message('remove'), + "#{ApplicationController.root_context}/profiles/remove_project?id=#{@profile.id}&project_id=#{project.id}", + :class => 'link-action', + :id => "link-remove-#{project.key.parameterize}" -%> + </td> + <td><%= h project.name -%> <span class="small gray"><%= h project.key -%></span></td> + </tr> <% end %> - </select> - </td> - <td align="center" style="padding: 0 10px;"> - <button id="select_right" onclick="SelectBox.move('from', 'to');SelectBox.sort('to');SelectBox.redisplay('to');return false;"><%= message('select_verb').downcase -%> »</button><br/> - <button id="select_right_all" onclick="SelectBox.move_all('from', 'to');return false;"><%= message('select_all').downcase -%> »</button><br/><br/> - <button id="select_left" onclick="SelectBox.move('to', 'from');return false;">« <%= message('unselect_verb').downcase -%></button><br/> - <button id="select_left_all" onclick="SelectBox.move_all('to', 'from');return false;">« <%= message('unselect_all').downcase -%></button> - </td> - <td class="box" style="padding: 5px 10px;" valign="top"> - <h3><%= message('quality_profiles.associated_projects') -%></h3> - <select name="projects[]" id="to" size="10" multiple="multiple" style="min-width: 300px;margin: 5px 0;"> - <%= options_from_collection_for_select(@profile.projects, "id", "name") %> - </select><br/> - <div style="padding:5px 0"> - <input type="submit" id="save" value="<%= message('save') -%>" onclick="SelectBox.select_all('to');submit();"/> - </div> - </td> -</tr> -</table> -</form> -<script> -SelectBox.init('from'); -SelectBox.init('to'); -</script> + </tbody> + <tfoot> + <tr> + <td colspan="2"> + <%= link_to_action message('quality_profiles.remove_projects_action'), + "#{ApplicationController.root_context}/profiles/remove_projects?id=#{@profile.id}", + :class => 'link-action', + :id => "link-remove-projects" -%> + </td> + </tr> + </tfoot> + </table> -<% else %> - <% if @profile.projects.empty? %> - <p><%= message('quality_profiles.no_projects_associated_to_profile_x', :params => @profile.name) -%></p> + <% end %> <% else %> - <p><%= message('quality_profiles.projects_warning') -%></p> - <ol> - <% @profile.projects.each do |project| %> - <li><%= project.name %></li> + + <% if @profile.projects.empty? %> + <p><%= message('quality_profiles.no_projects_associated_to_profile_x', :params => @profile.name) -%></p> + <% else %> + <p><%= message('quality_profiles.projects_warning') -%></p> + + <table class="data"> + <thead> + <tr> + <th></th> + </tr> + </thead> + <tbody> + <% @profile.projects.each do |project| %> + <tr class="<%= cycle('even', 'odd') -%>"> + <td><%= h project.name -%> <span class="small gray"><%= h project.key -%></span></td> + </tr> + <% end %> + </tbody> + </table> <% end %> - </ol> <% end %> -<% end %> </div>
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/project/profile.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/project/profile.html.erb new file mode 100644 index 00000000000..a52e06af2ec --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/project/profile.html.erb @@ -0,0 +1,40 @@ +<h1 class="marginbottom10"><%= message('project_quality_profile.page') -%></h1> + +<table class="data"> + <thead> + <tr> + <th><%= message 'language' -%></th> + <th>Quality Profile</th> + </tr> + </thead> + <tbody> + <% + Api::Utils.languages.sort_by { |l| l.getKey() }.each do |language| + selected_profile=@project.profile(language.getKey(), false) + %> + <tr class="<%= cycle 'even', 'odd' -%>"> + <td class="thin"><%= h language.getName() -%></td> + <td> + <form id="form-<%= language.getKey().parameterize -%>" method="POST" action="<%= ApplicationController.root_context -%>/project/set_profile"> + <input type="hidden" name="id" value="<%= @project.id -%>"/> + <input type="hidden" name="language" value="<%= language.getKey() -%>"/> + + <select id="select-profiles-<%= language.getKey().parameterize -%>" name="profile_id"> + <option value="" <%= "selected='selected'" unless selected_profile -%>><%= message 'project_quality_profile.default_profile' -%></option> + <optgroup> + <% + profiles = Api::Utils.insensitive_sort(Profile.all_by_language(language.getKey())) { |profile| profile.name } + profiles.each do |profile| + %> + <option value="<%= profile.id -%>" <%= "selected='selected'" if selected_profile && selected_profile.id==profile.id -%>><%= h profile.name -%></option> + <% end %> + </optgroup> + </select> + + <%= submit_tag message('update_verb'), :id => "submit-#{language.getKey()}", :disable_with => message('updating') %> + </form> + </td> + </tr> + <% end %> + </tbody> +</table> diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/project/quality_profile.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/project/quality_profile.html.erb deleted file mode 100644 index f75218f7db9..00000000000 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/project/quality_profile.html.erb +++ /dev/null @@ -1,23 +0,0 @@ -<h1><%= message('project_quality_profile.page') -%></h1> -<br/> -<% - form_tag( {:action => 'update_quality_profile', :id => @project.id }) do - project_profile = @project.profile -%> - - <span style= "padding-right: 10px"><%= message('project_quality_profile.select_profile_for_x', :params => @project.name) -%></span> - - <select name="quality_profile" id="quality_profile"> - <% - @profiles.each do |profile| - should_be_selected = (project_profile && project_profile==profile) || (!project_profile && profile.default_profile) - label = profile.name - label += ' (' + message('project_quality_profile.default_profile') + ')' if profile.default_profile - %> - <option <%= 'selected' if should_be_selected -%> value="<%= profile.id -%>"><%= label -%></option> - <% end %> - </select> - - <%= submit_tag message('update_verb'), :id => 'update_profile' %> - -<% end %> diff --git a/sonar-server/src/main/webapp/WEB-INF/db/migrate/331_remove_projects_profile_id.rb b/sonar-server/src/main/webapp/WEB-INF/db/migrate/331_remove_projects_profile_id.rb new file mode 100644 index 00000000000..68fc65062e4 --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/db/migrate/331_remove_projects_profile_id.rb @@ -0,0 +1,45 @@ +# +# 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 +# + +# +# Sonar 3.3 +# +class RemoveProjectsProfileId < ActiveRecord::Migration + + class Profile < ActiveRecord::Base + set_table_name 'rules_profiles' + end + + class Project < ActiveRecord::Base + belongs_to :profile + end + + class Property < ActiveRecord::Base + end + + def self.up + projects=Project.find(:all, :conditions => ['profile_id is not null and copy_resource_id is null'], :include => :profile) + projects.each do |project| + Property.create(:prop_key => "sonar.profile.#{project.profile.language}", :text_value => project.profile.name, :resource_id => project.id) + end + remove_column('projects', 'profile_id') + end + +end |