From: Jean-Baptiste Lievremont Date: Wed, 11 Dec 2013 17:31:45 +0000 (+0100) Subject: Duplicate rules configuration to prepare for pure ES implementation X-Git-Tag: 4.2~999 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=951c3928f8de03438edbeaab37176e1e8ac1dc19;p=sonarqube.git Duplicate rules configuration to prepare for pure ES implementation --- diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/new_rules_configuration_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/new_rules_configuration_controller.rb new file mode 100644 index 00000000000..66caee17833 --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/new_rules_configuration_controller.rb @@ -0,0 +1,444 @@ +# +# SonarQube, open source software quality management tool. +# Copyright (C) 2008-2013 SonarSource +# mailto:contact AT sonarsource DOT com +# +# SonarQube 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. +# +# SonarQube 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 this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +require 'cgi' + +class NewRulesConfigurationController < ApplicationController + + SECTION=Navigation::SECTION_QUALITY_PROFILES + + STATUS_ACTIVE = "ACTIVE" + STATUS_INACTIVE = "INACTIVE" + + ANY_SELECTION = [] + RULE_PRIORITIES = Sonar::RulePriority.as_options.reverse + + def index + require_parameters :id + + @profile = Profile.find(params[:id]) + add_breadcrumbs ProfilesController::root_breadcrumb, Api::Utils.language_name(@profile.language), + {:name => @profile.name, :url => {:controller => 'new_rules_configuration', :action => 'index', :id => @profile.id}} + + init_params() + + @select_repositories = ANY_SELECTION + java_facade.getRuleRepositoriesByLanguage(@profile.language).collect { |repo| [repo.getName(true), repo.getKey()] }.sort + @select_priority = ANY_SELECTION + RULE_PRIORITIES + @select_activation = [[message('any'), 'any'], [message('active'), STATUS_ACTIVE], [message('inactive'), STATUS_INACTIVE]] + @select_inheritance = [[message('any'), 'any'], [message('rules_configuration.not_inherited'), 'NOT'], [message('rules_configuration.inherited'), 'INHERITED'], + [message('rules_configuration.overrides'), 'OVERRIDES']] + @select_status = ANY_SELECTION + [[message('rules.status.beta'), Rule::STATUS_BETA], + [message('rules.status.deprecated'), Rule::STATUS_DEPRECATED], + [message('rules.status.ready'), Rule::STATUS_READY]] + @select_sort_by = [[message('rules_configuration.rule_name'), Rule::SORT_BY_RULE_NAME], [message('rules_configuration.creation_date'), Rule::SORT_BY_CREATION_DATE]] + + begin + stop_watch = Internal.profiling.start("rules", "BASIC") + + criteria = { + :profile => @profile, :activation => @activation, :priorities => @priorities, :inheritance => @inheritance, :status => @status, + :repositories => @repositories, :searchtext => @searchtext, :include_parameters_and_notes => true, :language => @profile.language, :sort_by => @sort_by} + @rules = Rule.search(java_facade, criteria) + + unless @searchtext.blank? + if @activation==STATUS_ACTIVE + @hidden_inactives = Rule.search(java_facade, { + :profile => @profile, :activation => STATUS_INACTIVE, :priorities => @priorities, :status => @status, + :repositories => @repositories, :language => @profile.language, :searchtext => @searchtext, :include_parameters_and_notes => false}).size + + elsif @activation==STATUS_INACTIVE + @hidden_actives = Rule.search(java_facade, { + :profile => @profile, :activation => STATUS_ACTIVE, :priorities => @priorities, :status => @status, + :repositories => @repositories, :language => @profile.language, :searchtext => @searchtext, :include_parameters_and_notes => false}).size + end + end + + stop_watch.stop("found #{@rules.size} rules with criteria #{criteria.to_json}") + rescue + @rules = [] + end + @pagination = Api::Pagination.new(params) + @pagination.count = @rules.size + @current_rules = @rules[@pagination.offset, @pagination.limit] + end + + + # + # + # POST /rules_configuration/revert_rule?id=&active_rule_id= + # + # + def revert_rule + verify_post_request + access_denied unless has_role?(:profileadmin) + require_parameters :id, :active_rule_id + id = params[:id].to_i + rule_id = params[:active_rule_id].to_i + java_facade.revertRule(id, rule_id, current_user.name) + redirect_to request.query_parameters.merge({:action => 'index', :id => params[:id], :commit => nil}) + end + + + # + # + # POST /rules_configuration/activate_rule?id=&rule_id=&level= + # + # If the parameter "level" is blank or null, then the rule is removed from the profile. + # + # + def activate_rule + verify_post_request + access_denied unless has_role?(:profileadmin) + require_parameters :id, :rule_id + profile = Profile.find(params[:id].to_i) + if profile + rule=Rule.first(:conditions => ["id = ? and status <> ?", params[:rule_id].to_i, Rule::STATUS_REMOVED]) + priority=params[:level] + + active_rule=profile.active_by_rule_id(rule.id) + if priority.blank? + # deactivate the rule + if active_rule + java_facade.ruleDeactivated(profile.id, active_rule.id, current_user.name) + active_rule.destroy + active_rule=nil + end + else + # activate the rule + activated = false + if active_rule.nil? + active_rule = ActiveRule.new(:profile_id => profile.id, :rule => rule) + rule.parameters.select { |p| p.default_value.present? }.each do |p| + active_rule.active_rule_parameters.build(:rules_parameter => p, :value => p.default_value) + end + activated = true + end + old_severity = active_rule.failure_level + active_rule.failure_level=Sonar::RulePriority.id(priority) + active_rule.save! + if activated + java_facade.ruleActivated(profile.id, active_rule.id, current_user.name) + else + java_facade.ruleSeverityChanged(profile.id, active_rule.id, old_severity, active_rule.failure_level, current_user.name) + end + end + if active_rule + active_rule.reload + end + + render :update do |page| + page.replace_html("rule_#{rule.id}", :partial => 'rule', :object => rule, :locals => {:profile => profile, :rule => rule, :active_rule => active_rule}) + page.assign('localModifications', true) + end + end + end + + + # + # + # GET /rules_configuration/new/?rule_id= + # + # + def new + # form to duplicate a rule + access_denied unless has_role?(:profileadmin) + require_parameters :id, :rule_id + @profile = Profile.find(params[:id].to_i) + add_breadcrumbs ProfilesController::root_breadcrumb, Api::Utils.language_name(@profile.language), {:name => @profile.name, :url => {:controller => 'new_rules_configuration', :action => 'index', :id => @profile.id}} + + @rule = Rule.find(params[:rule_id]) + end + + # + # + # POST /rules_configuration/create/?rule_id=&rule[name]=&... + # + # + def create + verify_post_request + access_denied unless has_role?(:profileadmin) + require_parameters :id, :rule_id + profile = Profile.find(params[:id].to_i) + template=Rule.find(params[:rule_id]) + # TODO Call Internal.rule.create(...) ? + rule=Rule.create(params[:rule].merge( + { + :priority => Sonar::RulePriority.id(params[:rule][:priority]), + :parent_id => template.id, + :plugin_name => template.plugin_name, + :cardinality => 'SINGLE', + :plugin_rule_key => "#{template.plugin_rule_key}_#{Time.now.to_i}", + :plugin_config_key => template.plugin_config_key, + :status => Rule::STATUS_READY, + :language => profile.language + } + )) + + template.parameters.each do |template_parameter| + rule.rules_parameters.build(:name => template_parameter.name, :param_type => template_parameter.param_type, :description => template_parameter.description, + :default_value => params[:rule_param][template_parameter.name]) + end + + if rule.save + Internal.rules.saveOrUpdate(rule.id) + redirect_to :action => 'index', :id => profile.id, :searchtext => "\"#{rule.name}\"", :rule_activation => 'INACTIVE', "plugins[]" => rule.plugin_name + + else + flash[:error]=message('rules_configuration.rule_not_valid_message_x', :params => rule.errors.full_messages.join('
')) + redirect_to :action => 'new', :id => profile.id, :rule_id => params[:rule_id] + end + end + + + # deprecated since 2.3 + def export + redirect_to request.query_parameters.merge({:controller => 'profiles', :action => 'export'}) + end + + # + # + # GET /rules_configuration/new/?rule_id= + # + # + def edit + # form to edit a rule + access_denied unless has_role?(:profileadmin) + require_parameters :id, :rule_id + @profile = Profile.find(params[:id]) + @rule = Rule.find(params[:rule_id]) + if !@rule.editable? + redirect_to :action => 'index', :id => params[:id] + end + end + + # + # + # POST /rules_configuration/update/?rule_id=&rule[name]=&... + # + # + def update + verify_post_request + access_denied unless has_role?(:profileadmin) + require_parameters :id, :rule_id + rule=Rule.find(params[:rule_id]) + if rule.editable? + rule.name=params[:rule][:name] + rule.description=params[:rule][:description] + rule.priority=Sonar::RulePriority.id(params[:rule][:priority]) + rule.parameters.each do |parameter| + parameter.default_value=params[:rule_param][parameter.name] + parameter.save + end + if rule.save + Internal.rules.saveOrUpdate(rule.id) + redirect_to :action => 'index', :id => params[:id], :searchtext => "\"#{rule.name}\"", :rule_activation => '', "plugins[]" => rule.plugin_name + else + flash[:error]=message('rules_configuration.rule_not_valid_message_x', :params => rule.errors.full_messages.join('
')) + redirect_to :action => 'new', :id => params[:id], :rule_id => params[:rule_id] + end + else + flash[:error]='Unknown rule' + redirect_to :action => 'index', :id => params[:id] + end + end + + + # + # + # POST /rules_configuration/delete/?rule_id= + # + # + def delete + verify_post_request + access_denied unless has_role?(:profileadmin) + require_parameters :id, :rule_id + rule=Rule.find(params[:rule_id]) + if rule.editable? + rule.status=Rule::STATUS_REMOVED + rule.save + Internal.rules.saveOrUpdate(rule.id) + + # it's mandatory to execute 'destroy_all' but not 'delete_all' because active_rule_parameters must + # also be destroyed in cascade. + ActiveRule.destroy_all("rule_id=#{rule.id}") + flash[:notice]=message('rules_configuration.rule_deleted') + else + flash[:error]=message('rules_configuration.unknown_rule') + end + redirect_to :action => 'index', :id => params[:id] + end + + # + # + # POST /rules_configuration/bulk_edit?id=&bulk_rule_ids=&bulk_action= + # + # Values of the parameter 'bulk_action' : + # - 'activate' : activate all the selected rules with their default priority + # - 'deactivate' : deactivate all the selected rules + # + # + def bulk_edit + verify_post_request + access_denied unless has_role?(:profileadmin) + require_parameters :id, :bulk_rule_ids, :bulk_action + profile = Profile.find(params[:id].to_i) + rule_ids = params[:bulk_rule_ids].split(',').map { |id| id.to_i } + activation=params[:rule_activation] || STATUS_ACTIVE + + case params[:bulk_action] + when 'activate' + count=activate_rules(profile, rule_ids) + flash[:notice]=message('rules_configuration.x_rules_have_been_activated', :params => count) + activation=STATUS_ACTIVE if activation==STATUS_INACTIVE + + when 'deactivate' + count=deactivate_rules(profile, rule_ids) + flash[:notice]=message('rules_configuration.x_rules_have_been_deactivated', :params => count) + activation=STATUS_INACTIVE if activation==STATUS_ACTIVE + end + + url_parameters=request.query_parameters.merge({:action => 'index', :bulk_action => nil, :bulk_rule_ids => nil, :id => profile.id, :rule_activation => activation}) + redirect_to url_parameters + end + + + def update_param + verify_post_request + access_denied unless has_role?(:profileadmin) + require_parameters :profile_id, :param_id, :active_rule_id + profile = Profile.find(params[:profile_id].to_i) + rule_param = RulesParameter.find(params[:param_id].to_i) + active_rule = ActiveRule.find(params[:active_rule_id].to_i) + # As the active param can be null, we should not raise a RecordNotFound exception when it's not found (as it would be done when using find(:id) function) + active_param = ActiveRuleParameter.find_by_id(params[:id].to_i) if params[:id].to_i > 0 + value = params[:value] + if value != "" + active_param = ActiveRuleParameter.new(:rules_parameter => rule_param, :active_rule => active_rule) if active_param.nil? + old_value = active_param.value + active_param.value = value + if active_param.save! && active_param.valid? + active_param.reload + java_facade.ruleParamChanged(profile.id, active_rule.id, rule_param.name, old_value, value, current_user.name) + end + elsif !active_param.nil? + old_value = active_param.value + active_param.destroy + java_facade.ruleParamChanged(profile.id, active_rule.id, rule_param.name, old_value, nil, current_user.name) + end + # let's reload the active rule + active_rule = ActiveRule.find(active_rule.id) + render :partial => 'rule', :locals => {:profile => profile, :rule => active_rule.rule, :active_rule => active_rule} + end + + + def update_rule_note + verify_post_request + access_denied unless has_role?(:profileadmin) + require_parameters :rule_id + rule = Rule.find(params[:rule_id]) + note = rule.note + unless note + note = RuleNote.new({:rule => rule}) + # set the note on the rule to avoid reloading the rule + rule.note = note + end + note.text = params[:text] + note.user_login = current_user.login + note.save! + render :partial => 'rule_note', :locals => {:rule => rule} + end + + + def update_active_rule_note + verify_post_request + access_denied unless has_role?(:profileadmin) + require_parameters :active_rule_id, :note + active_rule = ActiveRule.find(params[:active_rule_id]) + note = active_rule.note + unless note + note = ActiveRuleNote.new({:active_rule => active_rule}) + # set the note on the rule to avoid reloading the rule + active_rule.note = note + end + note.text = params[:note] + note.user_login = current_user.login + note.save! + render :partial => 'active_rule_note', :locals => {:active_rule => active_rule, :profile => active_rule.rules_profile} + end + + + def delete_active_rule_note + verify_post_request + access_denied unless has_role?(:profileadmin) + require_parameters :active_rule_id + active_rule = ActiveRule.find(params[:active_rule_id]) + active_rule.note.destroy if active_rule.note + active_rule.note = nil + render :partial => 'active_rule_note', :locals => {:active_rule => active_rule, :profile => active_rule.rules_profile} + end + + + private + + # return the number of newly activated rules + def activate_rules(profile, rule_ids) + count=0 + rule_ids_to_activate=(rule_ids - profile.active_rules.map { |ar| ar.rule_id }) + unless rule_ids_to_activate.empty? + rules_to_activate=Rule.all(:conditions => ["status <> ? AND id IN (?)", Rule::STATUS_REMOVED, rule_ids_to_activate]) + count = rules_to_activate.size + rules_to_activate.each do |rule| + active_rule = profile.active_rules.create(:rule => rule, :failure_level => rule.priority) + java_facade.ruleActivated(profile.id, active_rule.id, current_user.name) + end + end + count + end + + def deactivate_rules(profile, rule_ids) + count=0 + profile.active_rules.each do |ar| + if rule_ids.include?(ar.rule_id) && !ar.inheritance.present? + java_facade.ruleDeactivated(profile.id, ar.id, current_user.name) + ar.destroy + count+=1 + end + end + count + end + + def init_params + @id = params[:id] + @priorities = filter_any(params[:priorities]) || [''] + @repositories = filter_any(params[:repositories]) || [''] + @activation = params[:rule_activation] || STATUS_ACTIVE + @inheritance = params[:inheritance] || 'any' + @status = params[:status] + @sort_by = !params[:sort_by].blank? ? params[:sort_by] : Rule::SORT_BY_RULE_NAME + @searchtext = params[:searchtext] + end + + def filter_any(array) + if array && array.size>1 && array.include?('') + array=[''] #keep only 'any' + end + array + end + +end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/helpers/new_rules_configuration_helper.rb b/sonar-server/src/main/webapp/WEB-INF/app/helpers/new_rules_configuration_helper.rb new file mode 100644 index 00000000000..6932df3f85e --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/helpers/new_rules_configuration_helper.rb @@ -0,0 +1,86 @@ +# +# SonarQube, open source software quality management tool. +# Copyright (C) 2008-2013 SonarSource +# mailto:contact AT sonarsource DOT com +# +# SonarQube 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. +# +# SonarQube 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 this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +module NewRulesConfigurationHelper + include PropertiesHelper + + PARAM_TYPE_STRING_LIST = "s{}" + PARAM_TYPE_INTEGER_LIST = "i{}" + + # Kept for compatibility with old rule param type + def type_with_compatibility(type) + return PropertyType::TYPE_STRING if type == 's' + return PropertyType::TYPE_STRING if type == PARAM_TYPE_STRING_LIST + return PropertyType::TYPE_INTEGER if type == 'i' + return PropertyType::TYPE_INTEGER if type == PARAM_TYPE_INTEGER_LIST + return PropertyType::TYPE_BOOLEAN if type == 'b' + return PropertyType::TYPE_REGULAR_EXPRESSION if type == 'r' + return PropertyType::TYPE_STRING if is_set(type) + + type + end + + def readable_type(param_type) + type=type_with_compatibility(param_type) + + return "Set of comma delimited strings" if param_type == PARAM_TYPE_STRING_LIST + return "Number" if type == PropertyType::TYPE_INTEGER + return "Set of comma delimited numbers" if param_type == PARAM_TYPE_INTEGER_LIST + return "Regular expression" if type == PropertyType::TYPE_REGULAR_EXPRESSION + return "Set of comma delimited values" if is_set(param_type) + "" + end + + def param_value_input(parameter, value, options = {}) + type=type_with_compatibility(parameter.param_type) + name = options[:name] || 'value' + property_input_field name, type, value, 'WIDGET', {:id => parameter.id, :size => options[:size] }.update(options) + end + + def is_set(type) + type.at(1) == "[" && type.ends_with?("]") + end + + def validate_rule_param(attribute, param_type, errors, value) + return if attribute.nil? or attribute.length == 0 + + type=type_with_compatibility(param_type) + + if is_set_type + attribute.split(',').each do |v| + if !get_allowed_tokens.include?(v) + errors.add("#{value}", "'#{v}' must be one of : " + get_allowed_tokens.join(', ')) + end + end + elsif param_type == RulesConfigurationHelper::PARAM_TYPE_INTEGER_LIST + attribute.split(',').each do |n| + if !Api::Utils.is_integer?(n) + errors.add("#{value}", "'#{n}' must be an integer.") + end + end + elsif type == PropertyType::TYPE_REGULAR_EXPRESSION + errors.add("#{value}", "'#{attribute}' must be a regular expression") unless Api::Utils.is_regexp?(attribute) + elsif type == PropertyType::TYPE_INTEGER + errors.add("#{value}", "'#{attribute}' must be an integer.") unless Api::Utils.is_integer?(attribute) + elsif type == PropertyType::TYPE_BOOLEAN + errors.add("#{value}", "'#{attribute}' must be one of : true,false") unless Api::Utils.is_boolean?(attribute) + end + end +end + diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/new_rules_configuration/_active_rule_note.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/new_rules_configuration/_active_rule_note.html.erb new file mode 100644 index 00000000000..cc153964faf --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/new_rules_configuration/_active_rule_note.html.erb @@ -0,0 +1,70 @@ +<% #locals = active_rule, profile + note = active_rule.note + active_note_detail_div_id = "and_" + active_rule.id.to_s + add_active_note_button_id = "aanb_" + active_rule.id.to_s + edit_active_note_link_id = "eanl_" + active_rule.id.to_s + delete_active_note_link_id = "danl_" + active_rule.id.to_s + active_note_form_div_id = "anf_" + active_rule.id.to_s + active_note_textarea_id = "ant_" + active_rule.id.to_s + submit_active_note_update_button_id = "sanub_" + active_rule.id.to_s +%> + +
+ <% if note %> +
+ + <%= note.user.name -%> (<%= distance_of_time_in_words_to_now(note.updated_at) -%>)  + <% if profiles_administrator? %> + |   + <%= message('edit') %> +   + <%=message('delete')-%> + <% end %> + +

<%= note.html_text -%>

+
+ <% elsif profiles_administrator? %> + <%= message('rules_configuration.add_note') -%> + <% end %> +
+ +<% if profiles_administrator? %> +
+ + + + + + + + + + + +
+<% end %> diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/new_rules_configuration/_rule.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/new_rules_configuration/_rule.html.erb new file mode 100644 index 00000000000..06d3415d04c --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/new_rules_configuration/_rule.html.erb @@ -0,0 +1,121 @@ + +
+ <% enable_modification = profiles_administrator? + select_box_id = "levels_select_#{rule.id}" + check_box_id = "levels_check_#{rule.id}" + activate_rule = "$j.ajax({url:'#{ApplicationController.root_context}/new_rules_configuration/activate_rule/#{profile.id}?rule_id=#{rule.id}',type: 'POST', + beforeSend: function(request){$j('#levels_#{rule.id}').replaceWith('');}, + data: 'level='+ get_level_for_rule($j('#levels_select_#{rule.id} :selected'),$j('#levels_check_#{rule.id}'))});" + changel_level = "if($j('#levels_check_#{rule.id}').prop('checked')) + {$j.ajax({url:'#{ApplicationController.root_context}/new_rules_configuration/activate_rule/#{profile.id}?rule_id=#{rule.id}',type:'POST', + beforeSend:function(request){$j('#levels_#{rule.id}').replaceWith('');}, + data:'level='+$j('#levels_select_#{rule.id} :selected').val()})}" + %> + + <%= check_box_tag(check_box_id, 'yes', (!active_rule.nil?), :onclick => activate_rule, :disabled => !enable_modification || (active_rule && (active_rule.inherited? || active_rule.overrides?))) %> + <%= select_tag(select_box_id, options_for_select(RulesConfigurationController::RULE_PRIORITIES, (active_rule.nil? ? rule.priority_text : active_rule.priority_text)), + {:onchange => changel_level, :disabled => (!(enable_modification) || active_rule.nil?)}) %> + + <% if active_rule %> + <% if active_rule.inherited? %> + Inherited from parent + <% elsif active_rule.overrides? %> + Overrides parent definition + <% end %> + <% end %> +
+ + + + <% unless rule.ready? %> +
+ <% if rule.beta? %> + <%= message('rules.status.beta') %> + <% elsif rule.deprecated? %> + <%= message('rules.status.deprecated') %> + <% end %> +
+ <% end %> + +
<%= link_to_function("#{h rule.name}", nil, :class => "") do |page| + page.toggle "desc_#{rule.id}" + end + %>
+ +
+ + +
+ <%= render :partial => 'rule_note', :locals => {:rule => rule} %> +
+ + <% + ancestor_profile = profile.parent + ancestor_active_rule = ancestor_profile.active_by_rule_id(rule.id) if ancestor_profile && active_rule && (active_rule.inherited? || active_rule.overrides?) + if ancestor_active_rule || !rule.parameters.empty? + %> + + <% + if ancestor_active_rule + ancestor_active_rule_link = link_to ancestor_profile.name, :controller => 'rules_configuration', :action => 'index', + :id => ancestor_profile.id, :rule_id => rule.id, :anchor => 'rule' + rule.id.to_s + %> + + + + <% end %> + <% rule.parameters.sort.each do |parameter| + active_parameter = active_rule.active_param_by_param_id(parameter.id) if active_rule + %> + + <%= render :partial => 'rule_param', :object => nil, + :locals => {:parameter => parameter, :active_parameter => active_parameter, :profile => profile, :rule => rule, + :active_rule => active_rule, :ancestor_active_rule => ancestor_active_rule} %> + + <% + end + %> +
+ <%= message(active_rule.inherited? ? 'rules_configuration.rule_inherited_from_profile_x' : 'rules_configuration.rule_overriding_from_profile_x', + :params => ancestor_active_rule_link) -%> + <% if ancestor_active_rule.priority != active_rule.priority %> + Overrides parent definition + <%= message('rules_configuration.original_severity') -%> + : <%= ancestor_active_rule.priority_text -%> + <% end %> + <% if profiles_administrator? && active_rule.overrides? %> +
+ +
+ <% end %> +
+ <% end %> + + <% if active_rule %> +
+ <%= render :partial => 'active_rule_note', :locals => {:active_rule => active_rule, :profile => profile} %> +
+ <% end %> + + <% if profiles_administrator? %> + <% if rule.template? %> + <%= link_to message('rules_configuration.copy_rule'), {:action => 'new', :id => profile.id, :rule_id => rule.id}, :id => "copy-#{u rule.key}", :class => 'link-action spacer-right' %> + <% end %> + <% if rule.editable? %> + <%= link_to message('rules_configuration.edit_rule'), {:action => 'edit', :id => profile.id, :rule_id => rule.id}, :class => 'link-action spacer-right' %> + <% end %> + <% end %> + +
+ <%= message('rules_configuration.repository') %>: <%= rule.repository_key %> +  <%= image_tag 'sep12.png' -%>  + <%= message('key') %>: <%= rule.plugin_rule_key %> +  <%= image_tag 'sep12.png' -%>  + <% if rule.removed? %> + <%= message('rules_configuration.removed_since') %>: <%= human_short_date(rule.updated_at) %> + <% else %> + <%= message('rules_configuration.available_since') %> <%= human_short_date(rule.created_at) %> + <% end %> +
+
+ diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/new_rules_configuration/_rule_note.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/new_rules_configuration/_rule_note.html.erb new file mode 100644 index 00000000000..bff449efeec --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/new_rules_configuration/_rule_note.html.erb @@ -0,0 +1,65 @@ +<% #locals = rule + note = rule.note + note_detail_div_id = "nd_" + rule.id.to_s + note_extend_link_id = "nel_" + rule.id.to_s + note_form_div_id = "nf_" + rule.id.to_s + note_textarea_id = "nt_" + rule.id.to_s + submit_note_update_button_id = "snub_" + rule.id.to_s +%> + +
+
+ <% if rule.description.strip.start_with?('

') %> + <%= Internal.text.interpretMacros(rule.description) %> + <% else %> +

<%= Internal.text.interpretMacros(rule.description) %>

+ <% end %> +
+ + <% if note && !note.text.strip.blank? %> +

<%= note.html_text -%>

+ <% end %> + + <% if profiles_administrator? %> + + <% end %> +
+ +<% if profiles_administrator? %> + +<% end %> diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/new_rules_configuration/_rule_param.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/new_rules_configuration/_rule_param.html.erb new file mode 100644 index 00000000000..dcd477ee187 --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/new_rules_configuration/_rule_param.html.erb @@ -0,0 +1,49 @@ +<% param_value = parameter.default_value || '' + param_value = active_parameter.value if active_parameter + active_param_id = active_parameter.id if active_parameter + active_rule_id = active_rule.id if active_rule + read_only = !active_rule || !profiles_administrator? +%> + +<%= parameter.name -%> + + +
+ + + + <%= param_value_input(parameter, param_value, :disabled => read_only) -%> + + <% unless read_only %> + <%= submit_tag(message('update_verb'), :id => 'submit_' + parameter.id.to_s) %> + + <% if active_parameter and active_parameter.errors.size>0 %> + <%= active_parameter.errors.on 'value' %> + <% end %> + <% end %> + + <% if active_rule && active_rule.overrides? && ancestor_active_rule + ancestor_param = ancestor_active_rule.active_param_by_param_id(parameter.id) + ancestor_value = ancestor_param && ancestor_param.value ? ancestor_param.value : '' + %> + <% if ancestor_value != param_value %> + Overrides parent definition + + <%= message('rules_configuration.original_value') -%> + : <%= ancestor_value.blank? ? '(' + message('rules_configuration.parent_parameter.empty') + ')' : ancestor_value -%> + + <% end %> + <% end %> + +
<%= h(parameter.description || "") -%> <%= ('(' + readable_type(parameter.param_type) + ')') if !readable_type(parameter.param_type).empty? -%>
+ +
+ diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/new_rules_configuration/edit.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/new_rules_configuration/edit.html.erb new file mode 100644 index 00000000000..fba58000636 --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/new_rules_configuration/edit.html.erb @@ -0,0 +1,69 @@ +

<%= link_to message('quality_profiles.quality_profiles'), :controller => 'profiles', :action => 'index' -%> / <%= h @profile.language -%> / <%= h @profile.name %>

+ +<%= render :partial => 'profiles/tabs', :locals => {:new_tab => 'Edit rule'} %> + +
+ + + +
+ + + + + + + + + + + + + + + + + <% @rule.parameters.sort{|x,y| x.name <=> y.name}.each do |parameter| %> + + + + + + <% end %> + + + + + + + + +
<%= message('template') -%>: <%= h @rule.parent.name -%>
<%= message('name') -%>:
<%= message('default_severity') -%>: + +
<%= parameter.name %>: + <%= param_value_input(parameter, "#{h parameter.default_value}", {:name => "rule_param[#{h parameter.name }]", :size => '80x10'}) -%> + <%= h parameter.description %> +
Description: + + <%= message('rules_configuration.html_allowed') -%> +
+ + + <%= message('cancel') -%> +
+
+
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/new_rules_configuration/index.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/new_rules_configuration/index.html.erb new file mode 100644 index 00000000000..9c8d6425d70 --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/new_rules_configuration/index.html.erb @@ -0,0 +1,169 @@ +
+ +<%= render :partial => 'profiles/tabs', :locals => {:selected_tab=>'Coding rules reloaded'} %> + +<% enable_modification = profiles_administrator? %> +
+ +<% form_tag({:action => 'index'}, {:id => 'rules-search-form', :method => 'get'}) do %> + <%= hidden_field_tag "sort_by", @sort_by, :id => 'sort_by' %> + +
+ + + + + + <% if @profile.inherited? %> + + <% end %> + +
+ +<% end %> +
+
+
    +
  • + +
  • + <% if enable_modification && @rules.size>0 %> +
  • +
    <%= message('bulk_change') -%>: +
    + + + <%= dropdown_tag "bulk_action", options_for_select([ ["", ""], [message('activate_all'), "activate"], [message('deactivate_all'), "deactivate"] ], ''), { + :width => '110px' + }, {:onChange => 'submitBulkForm()', :id => 'select-bulk-change'} -%> +
    +
    +
  • + <% end %> +
+

+ <% if @hidden_actives && @hidden_actives>0 %> + +<%= message('rules_configuration.x_found_in_active_rules', :params => @hidden_actives) -%><% end %> + <% if @hidden_inactives && @hidden_inactives>0 %> + +<%= message('rules_configuration.x_found_in_inactive_rules', :params => @hidden_inactives) -%><% end %> +

+
+ + + + + + + + + +<%= table_pagination(@pagination, :colspan => 2) { |label, page_id| link_to(label, params.merge({:page => page_id}))} -%> + + +<% if @current_rules.empty? %> + +<% end %> +<% + @current_rules.each do |rule| + active_rule = @profile.active_by_rule_id(rule.id) +%> + + <%= render :partial => 'rule', :object => rule, :locals => {:profile => @profile, :rule => rule, :active_rule => active_rule} %> + +<% end %> + +
<%= message('active') -%>/<%= message('severity') -%><%= message('name') -%> + [<%= link_to_function(message('rules_configuration.expand'), "expand_rules()") %> / <%= link_to_function(message('rules_configuration.collapse'), "collapse_rules()") %>] + <%= message('rules_configuration.sort_by') -%> + <% form_tag({:action => 'index'}, :class=> 'middle', :style => 'display:inline-block') do %> + <%= dropdown_tag "sort_by", options_for_select(@select_sort_by, @sort_by), { + :width => '120px' + }, {:id => 'select-rules-sort-by', :onChange => 'submitSortBy()'} -%> + <% end %> +
<%= message('no_results') -%>.
+
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/new_rules_configuration/new.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/new_rules_configuration/new.html.erb new file mode 100644 index 00000000000..c767c2059fd --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/new_rules_configuration/new.html.erb @@ -0,0 +1,53 @@ +
+<%= render :partial => 'profiles/tabs', :locals => {:new_tab => message('rules_configuration.tab.new_rule')} %> + +
+ +
+ + + + + + + + + + + + + + + + + <% @rule.parameters.sort{|x,y| x.name <=> y.name}.each do |parameter| %> + + + + + + <% end %> + + + + + + + + +
<%= message('template') -%>: <%= h @rule.name -%>
<%= message('name') -%>:
<%= message('default_severity') -%>: + +
<%= parameter.name %>: + <%= param_value_input(parameter, "", {:name => "rule_param[#{h parameter.name}]", :size => '80x10'}) -%> + <%= h parameter.description %> +
<%= message('description') -%>: + + <%= message('rules_configuration.html_allowed') -%> +
+ <%= message('cancel') -%> +
+
+
+
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/_tabs.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/_tabs.html.erb index 5a5ce051762..4fc5f49a68f 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/_tabs.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/profiles/_tabs.html.erb @@ -21,6 +21,9 @@
  • id="tab-changelog"><%= message('changelog') -%>
  • +
  • + id="tab-rules"><%= message('Coding rules reloaded') -%> +
  • <% if new_tab %>
  • <%= new_tab -%>