diff options
author | Fabrice Bellingard <bellingard@gmail.com> | 2012-01-23 18:03:19 +0100 |
---|---|---|
committer | Fabrice Bellingard <bellingard@gmail.com> | 2012-01-23 19:23:18 +0100 |
commit | 328abda6157af975f9251c854320f064dafa5a82 (patch) | |
tree | 3fedf2925645257438c99e0056ee59008690c632 /sonar-server | |
parent | 2044f95a1c1064f2cde28df0c33af633fdd8d8a2 (diff) | |
download | sonarqube-328abda6157af975f9251c854320f064dafa5a82.tar.gz sonarqube-328abda6157af975f9251c854320f064dafa5a82.zip |
SONAR-1492 Allow notes per quality rule
Admin page implemented
Diffstat (limited to 'sonar-server')
9 files changed, 244 insertions, 51 deletions
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/rules_configuration_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/rules_configuration_controller.rb index 4fb539ecf85..b8563fb4a70 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/rules_configuration_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/rules_configuration_controller.rb @@ -29,7 +29,9 @@ class RulesConfigurationController < ApplicationController RULE_PRIORITIES = Sonar::RulePriority.as_options.reverse # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html) - verify :method => :post, :only => ['activate_rule', 'update_param', 'bulk_edit', 'create', 'update', 'delete', 'revert_rule'], :redirect_to => { :action => 'index' } + verify :method => :post, + :only => ['activate_rule', 'update_param', 'bulk_edit', 'create', 'update', 'delete', 'revert_rule', 'update_note', 'delete_note'], + :redirect_to => { :action => 'index' } before_filter :admin_required, :except => [ 'index', 'export' ] @@ -312,6 +314,42 @@ class RulesConfigurationController < ApplicationController :locals => {:parameter => rule_param, :active_parameter => active_param, :profile => profile, :active_rule => active_rule, :is_admin => is_admin } end + + def update_note + if params[:is_active_rule] + rule = ActiveRule.find(params[:rule_id]) + else + rule = Rule.find(params[:rule_id]) + end + note = rule.note + unless note + if params[:is_active_rule] + note = ActiveRuleNote.new({:rule => rule}) + else + note = RuleNote.new({:rule => rule}) + end + # 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, :is_admin => true, :is_active_rule => params[:is_active_rule] } + end + + + def delete_note + if params[:is_active_rule] + rule = ActiveRule.find(params[:rule_id]) + else + rule = Rule.find(params[:rule_id]) + end + rule.note.destroy if rule.note + render :text => '' + end + + + private # return the number of newly activated rules diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/active_rule_note.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/active_rule_note.rb index 45bdfb4b8bb..b306bec7393 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/models/active_rule_note.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/models/active_rule_note.rb @@ -20,8 +20,17 @@ class ActiveRuleNote < ActiveRecord::Base belongs_to :active_rule alias_attribute :text, :data + alias_attribute :rule, :active_rule validates_presence_of :active_rule, :message => "can't be empty" validates_presence_of :user_login, :message => "can't be empty" + validates_length_of :data, :minimum => 1 + + def user + @user ||= + begin + user_login ? User.find(:first, :conditions => ['login=?', user_login]) : nil + end + end end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/rule_note.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/rule_note.rb index c879875a95f..ca7c805a4f7 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/models/rule_note.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/models/rule_note.rb @@ -23,5 +23,13 @@ class RuleNote < ActiveRecord::Base validates_presence_of :rule, :message => "can't be empty" validates_presence_of :user_login, :message => "can't be empty" + validates_length_of :data, :minimum => 1 + + def user + @user ||= + begin + user_login ? User.find(:first, :conditions => ['login=?', user_login]) : nil + end + end end diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/rules_configuration/_create_rule_note.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/rules_configuration/_create_rule_note.html.erb new file mode 100644 index 00000000000..ebc2ddaaa9a --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/rules_configuration/_create_rule_note.html.erb @@ -0,0 +1,48 @@ +<% #locals = rule, active_rule, is_admin + create_buttons_div_id = "cb_" + rule.id.to_s + create_rule_note_button_div_id = "cnb_" + rule.id.to_s + create_active_rule_note_button_div_id = "canb_" + rule.id.to_s + create_rule_note_form_div_id = "crnf_" + rule.id.to_s + create_active_rule_note_form_div_id = "carnf_" + rule.id.to_s + submit_rule_note_id = "srn_" + rule.id.to_s + submit_active_rule_note_id = "sarn_" + rule.id.to_s + rule_note_text_id = "rnt_" + rule.id.to_s + active_rule_note_text_id = "arnt_" + rule.id.to_s +%> + +<div style="margin-top: 10px;"> + +<div id="<%= create_buttons_div_id -%>"> + <input type="button" id="<%= create_rule_note_button_div_id -%>" value="<%= message('rules_configuration.add_note') -%>" + onclick="$('<%= create_buttons_div_id -%>').hide();$('<%= create_rule_note_form_div_id -%>').show();$('<%= rule_note_text_id -%>').focus();" + <%= 'style="display:none;"' if rule.note -%>> + <input type="button" id="<%= create_active_rule_note_button_div_id -%>" value="<%= message('rules_configuration.add_activation_note') -%>" + onclick="$('<%= create_buttons_div_id -%>').hide();$('<%= create_active_rule_note_form_div_id -%>').show();$('<%= active_rule_note_text_id -%>').focus();" + <%= 'style="display:none;"' if active_rule && active_rule.note -%>> +</div> + +<div id="<%= create_rule_note_form_div_id -%>" style="display: none" class="admin"> + <%= form_remote_tag :url => {:action => 'update_note', :rule_id => rule.id, :is_active_rule => false}, + :update => "rule_note_#{rule.id}", + :complete => "$('#{create_rule_note_form_div_id}').hide();$('#{create_buttons_div_id}').show();$('#{create_rule_note_button_div_id}').hide();" %> + <textarea name="text" id="<%= rule_note_text_id -%>" cols="100" rows="10" onkeyup="if (this.value=='') $('<%= submit_rule_note_id -%>').disabled=true; else $('<%= submit_rule_note_id -%>').disabled=false;"></textarea> + <div class="note" style="padding: 5px 0px"><%= message('rules_configuration.adding_note_decsription') -%></div> + <input type="submit" value="<%= message('rules_configuration.create_note') -%>" name="commit" id="<%= submit_rule_note_id -%>" disabled/> + <a href="#" onclick="$('<%= create_buttons_div_id -%>').show();$('<%= create_rule_note_form_div_id -%>').hide();return false;"><%= message('cancel') %></a> + </form> +</div> + +<% if active_rule%> +<div id="<%= create_active_rule_note_form_div_id -%>" style="display: none" class="admin"> + <%= form_remote_tag :url => {:action => 'update_note', :rule_id => active_rule.id, :is_active_rule => true}, + :update => "active_rule_note_#{active_rule.id}", + :complete => "$('#{create_active_rule_note_form_div_id}').hide();$('#{create_buttons_div_id}').show();$('#{create_active_rule_note_button_div_id}').hide();" %> + <textarea name="text" id="<%= active_rule_note_text_id -%>" cols="100" rows="10" onkeyup="if (this.value=='') $('<%= submit_active_rule_note_id -%>').disabled=true; else $('<%= submit_active_rule_note_id -%>').disabled=false;"></textarea> + <div class="note" style="padding: 5px 0px"><%= message('rules_configuration.adding_activation_note_decsription')-%></div> + <input type="submit" value="<%= message('rules_configuration.create_activation_note') -%>" name="commit" id="<%= submit_active_rule_note_id -%>" disabled/> + <a href="#" onclick="$('<%= create_buttons_div_id -%>').show();$('<%= create_active_rule_note_form_div_id -%>').hide();return false;"><%= message('cancel') %></a> + </form> +</div> +<% end %> + +</div>
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/rules_configuration/_rule.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/rules_configuration/_rule.html.erb index 8ca525c5202..da6cad72dd4 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/rules_configuration/_rule.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/rules_configuration/_rule.html.erb @@ -1,5 +1,8 @@ -<td nowrap valign="top" class="left" x="<%= active_rule.failure_level if active_rule -%>" width="1%"> - <form id="levels_<%= rule.id -%>" action=""> +<% color = cycle('even','odd') %> + +<tr id="rule_<%= rule.id -%>" class="<%= color -%>"> + <td nowrap valign="top" class="left" x="<%= active_rule.failure_level if active_rule -%>" width="1%"> + <form id="levels_<%= rule.id -%>" action=""> <% enable_modification = is_admin && !profile.provided? select_box_id = "levels_select_#{rule.id}" check_box_id = "levels_check_#{rule.id}" @@ -25,42 +28,76 @@ <img src="<%= ApplicationController.root_context -%>/images/overrides.png" alt="Overrides parent definition" title="<%= message('rules_configuration.overrides_parent_definition') -%>"/> <% end %> <% end %> - </form> -</td> -<td valign="top" class="left"> - <%= link_to_function("#{h rule.name}", nil, :class => "") do |page| + </form> + </td> + <td valign="top" class="left"> + <%= link_to_function("#{h rule.name}", nil, :class => "") do |page| page.toggle "desc_#{rule.id}" end - %> - <div id="desc_<%= rule.id -%>" class="rule_desc" style="display:none"> - <span class="subtitle"><%= message('key') -%>: <%= rule.plugin_rule_key -%></span> - <div style="margin:8px 0px"><%= rule.description %></div> - <table style="margin: 10px 0"> - <% rule.parameters.each do |parameter| - active_parameter = active_rule.active_param_by_param_id(parameter.id) if active_rule - %> - <tbody id="param_<%= parameter.id -%>"> - <%= render :partial => 'rule_param', :object => nil, - :locals => {:parameter => parameter, :active_parameter => active_parameter, :profile => profile, :active_rule => active_rule, :is_admin => is_admin } %> - </tbody> - <% end %> - </table> - <% if is_admin %> - <% if rule.template? %> - <%= button_to message('rules_configuration.copy_rule'), {:action => 'new', :id => profile.id, :rule_id => rule.id}, :id => "copy-#{u rule.key}" %> - <% end %> - <% if rule.editable? %> - <%= button_to message('rules_configuration.edit_rule'), :action => 'edit', :id => profile.id, :rule_id => rule.id %> - <% end %> - <% if active_rule && active_rule.overrides? %> - <%= button_to message('rules_configuration.revert_to_parent_definition'), :overwrite_params => {:action => 'revert_rule', :id => profile.id, :active_rule_id => active_rule.id} %><br/> - <% end %> - <% end %> - </div> -</td> -<td valign="top" class="right rule_plugin"> -<%= rule.plugin_name.capitalize %> -</td> -<script type="text/javascript"> + %> + </td> + <script type="text/javascript"> Form.reset($('levels_<%= rule.id -%>')); -</script> + </script> +</tr> + +<tr id="desc_<%= rule.id -%>" class="rule_detail <%= color -%>" style="display:none"> + <td colspan="3"> + <table width="100%"> + <tbody> + <tr> + <td width="50%"> + <h3><%= message('rules_configuration.rule_description') -%></h3> + <p><%= rule.description %></p> + <div id="rule_note_<%= rule.id -%>"> + <%= render :partial => 'rule_note', :locals => {:rule => rule, :is_admin => is_admin, :is_active_rule => false } %> + </div> + <% if active_rule %> + <div id="active_rule_note_<%= active_rule.id -%>"> + <%= render :partial => 'rule_note', :locals => {:rule => active_rule, :is_admin => is_admin, :is_active_rule => true } %> + </div> + <% end %> + <% if is_admin %> + <%= render :partial => 'create_rule_note', :locals => {:rule => rule, :active_rule => active_rule, :is_admin => is_admin } %> + <% end %> + </td> + <td class="separator"></td> + <td width="50%"> + <h3><%= message('rules_configuration.rule_identification') -%></h3> + <table style="margin-left:7px"> + <tbody> + <tr><td style="padding-right:10px"><%= message('plugin') -%>:</td><td><%= rule.plugin_name.capitalize %></td></tr> + <tr><td style="padding-right:10px"><%= message('key') -%>:</td><td><%= rule.plugin_rule_key %></td></tr> + <t/body> + </table> + <% unless rule.parameters.empty? %> + <br/> + <h3><%= message('rules_configuration.rule_parameters') -%></h3> + <table style="margin-left:7px"> + <% rule.parameters.each do |parameter| + active_parameter = active_rule.active_param_by_param_id(parameter.id) if active_rule + %> + <tbody id="param_<%= parameter.id -%>"> + <%= render :partial => 'rule_param', :object => nil, + :locals => {:parameter => parameter, :active_parameter => active_parameter, :profile => profile, :active_rule => active_rule, :is_admin => is_admin } %> + </tbody> + <% end %> + </table> + <% end %> + <% if is_admin %> + <% if rule.template? %> + <%= button_to message('rules_configuration.copy_rule'), {:action => 'new', :id => profile.id, :rule_id => rule.id}, :id => "copy-#{u rule.key}" %> + <% end %> + <% if rule.editable? %> + <%= button_to message('rules_configuration.edit_rule'), :action => 'edit', :id => profile.id, :rule_id => rule.id %> + <% end %> + <% if active_rule && active_rule.overrides? %> + <%= button_to message('rules_configuration.revert_to_parent_definition'), :overwrite_params => {:action => 'revert_rule', :id => profile.id, :active_rule_id => active_rule.id} %><br/> + <% end %> + <% end %> + </td> + </tr> + </tbody> + </table> + </td> +</tr> diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/rules_configuration/_rule_note.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/rules_configuration/_rule_note.html.erb new file mode 100644 index 00000000000..208a1fe98c4 --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/rules_configuration/_rule_note.html.erb @@ -0,0 +1,36 @@ +<% #locals = rule, is_admin, is_active_rule + submit_note_update_button_id = (is_active_rule ? 'a' : '') + "snub_" + rule.id.to_s +%> + +<% + if rule.note + note = rule.note +%> + <h3><%= is_active_rule ? message('rules_configuration.rule_activation_note') : message('rules_configuration.rule_note') -%></h3> + <div class="note"><%= note.user.name -%>, <%= l(note.updated_at) -%></div> + <div id="note_detail_<%= rule.id -%>"> + <p><%= sanitize(note.text) -%></p> + <% if is_admin %> + <div style="margin-bottom: 10px"> + <input type="button" value="<%= message('update_verb') -%>" onclick="$('note_detail_<%= rule.id -%>').hide();$('note_form_<%= rule.id -%>').show();"> + <%= button_to_remote message('delete'), + {:url => {:action => 'delete_note', :rule_id => rule.id, :is_active_rule => is_active_rule }, + :update => "#{'active_' if is_active_rule}rule_note_#{rule.id}", + :complete => "$('#{is_active_rule ? "canb_"+rule.rule.id.to_s : "cnb_"+rule.id.to_s}').show()", + :confirm => message('rules_configuration.confirm_delete_note')}, + {:class => 'red-button'} -%> + </div> + <% end %> + </div> + + <div id="note_form_<%= rule.id -%>" style="display: none" class="admin"> + <%= form_remote_tag :url => {:action => 'update_note', :rule_id => rule.id, :is_active_rule => is_active_rule}, + :update => "#{'active_' if is_active_rule}rule_note_#{rule.id}" %> + <textarea name="text" id="update_<%= 'active_' if is_active_rule -%>_rule_note_<%= rule.id -%>" cols="100" rows="10" + onkeyup="if (this.value=='') $('<%= submit_note_update_button_id -%>').disabled=true; else $('<%= submit_note_update_button_id -%>').disabled=false;"><%= h(note.text) -%></textarea> + <br/> + <input type="submit" value="<%= message('update_verb') -%>" name="commit" id="<%= submit_note_update_button_id -%>"/> + <a href="#" onclick="$('note_detail_<%= rule.id -%>').show();$('note_form_<%= rule.id -%>').hide();return false;"><%= message('cancel') %></a> + </form> + </div> +<% end %>
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/rules_configuration/_rule_param.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/rules_configuration/_rule_param.html.erb index 0e011d5322e..0a2ee16ba06 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/rules_configuration/_rule_param.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/rules_configuration/_rule_param.html.erb @@ -32,7 +32,13 @@ <span class="error"><%= active_parameter.errors.on 'value' %></span> <% end %> <% end %> - <span class="note"><%= h parameter.description -%></span> + </form> </td> </tr> +<tr> + <td></td> + <td style="padding-bottom:5px;"> + <span class="note" style="white-space: normal"><%= h parameter.description -%></span> + </td> +</tr> diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/rules_configuration/index.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/rules_configuration/index.html.erb index 484fce0b348..be2e5c9b50c 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/rules_configuration/index.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/rules_configuration/index.html.erb @@ -20,7 +20,7 @@ return !localModifications; } function toggle_rules(){ - $$('.rule_desc').each(function(element) { + $$('.rule_detail').each(function(element) { element.toggle(); }); } @@ -106,7 +106,6 @@ <tr> <th class="left" nowrap><%= message('active') -%>/<%= message('severity') -%></th> <th class="left"><%= message('name') -%> <span style="font-weight: normal">[<%= link_to_function(message('rules_configuration.expand_collapse'), "toggle_rules()") %>]</span></th> - <th class="right"><%= message('plugin') -%></th> </tr> </thead> <tbody> @@ -119,9 +118,9 @@ @rules.each do |rule| active_rule = @profile.active_by_rule_id(rule.id) %> - <tr id="rule_<%= rule.id -%>" class="<%= cycle('even','odd') -%>"> - <%= render :partial => 'rule', :object => rule, :locals => {:profile => @profile, :active_rule => active_rule, :is_admin => is_admin} %> - </tr> + + <%= render :partial => 'rule', :object => rule, :locals => {:profile => @profile, :active_rule => active_rule, :is_admin => is_admin} %> + <% end %> </tbody> </table> diff --git a/sonar-server/src/main/webapp/stylesheets/style.css b/sonar-server/src/main/webapp/stylesheets/style.css index 4bc8b09f896..b2438ffdec5 100644 --- a/sonar-server/src/main/webapp/stylesheets/style.css +++ b/sonar-server/src/main/webapp/stylesheets/style.css @@ -2046,32 +2046,44 @@ ul.bullet li { width: 100%; } -.rule_desc { +.rule_detail { color: #444; - padding: 2px 0; } -.rule_desc li { +.rule_detail > td > table { + margin: 4px; +} + +.rule_detail td { + vertical-align: text-top; +} + +.rule_detail li { list-style: disc outside; padding: 2px; } -.rule_desc ul { +.rule_detail ul { list-style: none outside; padding-left: 30px; } -.rule_desc pre, .rule_desc p { +.rule_detail pre, .rule_detail p { padding: 7px; } -.rule_desc pre { +.rule_detail pre { margin: 10px 0; font-family: "Courier New", Courier, monospace;; border: 1px dashed #aaa; font-size: 93%; } +.rule_detail .separator { + background: url('../images/sep12.png') center repeat-y; + min-width: 20px; +} + .tip:hover { background: #FFF; position: relative; |