]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-2694 Provide a new optional 'category' attribute on the @Property annotation
authorSimon Brandhof <simon.brandhof@gmail.com>
Mon, 15 Aug 2011 17:36:19 +0000 (19:36 +0200)
committerSimon Brandhof <simon.brandhof@gmail.com>
Mon, 15 Aug 2011 17:36:19 +0000 (19:36 +0200)
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java
plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/core.properties
sonar-plugin-api/src/main/java/org/sonar/api/Property.java
sonar-server/src/main/webapp/WEB-INF/app/controllers/project_controller.rb
sonar-server/src/main/webapp/WEB-INF/app/controllers/settings_controller.rb
sonar-server/src/main/webapp/WEB-INF/app/views/project/settings/_delete_project.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/project/settings/_exclusions.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/project/settings/_links.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/settings/_plugins.html.erb

index 60f7d250ba0c3608daaf0acdaf545aef4666b618..db162da7c70a1ff943981399ec100cfecd51e92f 100644 (file)
@@ -48,21 +48,25 @@ import java.util.List;
         key = CoreProperties.ORGANIZATION,
         name = "Organization",
         description = "Identify your installation. Required to generate the server key and to benefit from licensed plugins. Server must be restarted for the change to take effect.",
-        global = true),
+        global = true,
+        category = "General"
+    ),
     @Property(
         key = CoreProperties.SERVER_BASE_URL,
         defaultValue = CoreProperties.SERVER_BASE_URL_DEFAULT_VALUE,
         name = "Server base URL",
         description = "HTTP address of the Sonar server, such as <i>http://yourhost.yourdomain/sonar</i>. This value is used i.e. to create links in emails and to generate server key.",
         project = false,
-        global = true),
+        global = true,
+        category = "General"),
     @Property(
         key = CoreProperties.CORE_COVERAGE_PLUGIN_PROPERTY,
         defaultValue = "cobertura",
         name = "Code coverage plugin",
         description = "Key of the code coverage plugin to use.",
         project = true,
-        global = true),
+        global = true,
+        category = "Coverage"),
     @Property(
         key = CoreProperties.CORE_IMPORT_SOURCES_PROPERTY,
         defaultValue = "" + CoreProperties.CORE_IMPORT_SOURCES_DEFAULT_VALUE,
@@ -70,14 +74,16 @@ import java.util.List;
         description = "Set to false if sources should not be displayed, e.g. for security reasons.",
         project = true,
         module = true,
-        global = true),
+        global = true,
+        category = "General"),
     @Property(
         key = CoreProperties.CORE_TENDENCY_DEPTH_PROPERTY,
         defaultValue = "" + CoreProperties.CORE_TENDENCY_DEPTH_DEFAULT_VALUE,
         name = "Tendency period",
         description = TendencyDecorator.PROP_DAYS_DESCRIPTION,
         project = false,
-        global = true),
+        global = true,
+        category = "General"),
     @Property(
         key = CoreProperties.SKIP_TENDENCIES_PROPERTY,
         defaultValue = "" + CoreProperties.SKIP_TENDENCIES_DEFAULT_VALUE,
@@ -85,41 +91,47 @@ import java.util.List;
         description = "Skip calculation of measure tendencies",
         project = true,
         module = false,
-        global = true),
+        global = true,
+        category = "General"),
     @Property(
         key = CoreProperties.CORE_SKIPPED_MODULES_PROPERTY,
         name = "Exclude modules",
         description = "Maven artifact ids of modules to exclude (comma-separated).",
         project = true,
-        global = false),
+        global = false,
+        category = "General"),
     @Property(
         key = CoreProperties.CORE_RULE_WEIGHTS_PROPERTY,
         defaultValue = CoreProperties.CORE_RULE_WEIGHTS_DEFAULT_VALUE,
         name = "Rules weight",
         description = "A weight is associated to each priority to calculate the Rules Compliance Index.",
         project = false,
-        global = true),
+        global = true,
+        category = "General"),
     @Property(
         key = CoreProperties.CORE_FORCE_AUTHENTICATION_PROPERTY,
         defaultValue = "" + CoreProperties.CORE_FORCE_AUTHENTICATION_DEFAULT_VALUE,
         name = "Force user authentication",
         description = "Forcing user authentication stops un-logged users to access Sonar.",
         project = false,
-        global = true),
+        global = true,
+        category = "General"),
     @Property(
         key = CoreProperties.CORE_ALLOW_USERS_TO_SIGNUP_PROPERTY,
         defaultValue = "" + CoreProperties.CORE_ALLOW_USERS_TO_SIGNUP_DEAULT_VALUE,
         name = "Allow users to sign up online",
         description = "Users can sign up online.",
         project = false,
-        global = true),
+        global = true,
+        category = "General"),
     @Property(
         key = CoreProperties.CORE_DEFAULT_GROUP,
         defaultValue = CoreProperties.CORE_DEFAULT_GROUP_DEFAULT_VALUE,
         name = "Default user group",
         description = "Any new users will automatically join this group.",
         project = false,
-        global = true
+        global = true,
+        category = "General"
     ),
     @Property(
         key = CoreProperties.CORE_VIOLATION_LOCALE_PROPERTY,
@@ -127,7 +139,8 @@ import java.util.List;
         name = "Locale used for violation messages",
         description = "Locale to be used when generating violation messages. It's up to each rule engine to support this global internationalization property",
         project = true,
-        global = true),
+        global = true,
+        category = "General"),
     @Property(
         key = "sonar.timemachine.period1",
         name = "Period 1",
@@ -136,7 +149,8 @@ import java.util.List;
             "compare to previous analysis</li><li>A version, for example 1.2</li></ul>",
         project = false,
         global = true,
-        defaultValue = CoreProperties.TIMEMACHINE_DEFAULT_PERIOD_1
+        defaultValue = CoreProperties.TIMEMACHINE_DEFAULT_PERIOD_1,
+        category = "Time Machine"
     ),
     @Property(
         key = "sonar.timemachine.period2",
@@ -144,7 +158,8 @@ import java.util.List;
         description = "See the property 'Period 1'",
         project = false,
         global = true,
-        defaultValue = CoreProperties.TIMEMACHINE_DEFAULT_PERIOD_2
+        defaultValue = CoreProperties.TIMEMACHINE_DEFAULT_PERIOD_2,
+        category = "Time Machine"
     ),
     @Property(
         key = "sonar.timemachine.period3",
@@ -152,7 +167,8 @@ import java.util.List;
         description = "See the property 'Period 1'",
         project = false,
         global = true,
-        defaultValue = CoreProperties.TIMEMACHINE_DEFAULT_PERIOD_3
+        defaultValue = CoreProperties.TIMEMACHINE_DEFAULT_PERIOD_3,
+        category = "Time Machine"
     ),
     @Property(
         key = "sonar.timemachine.period4",
@@ -162,7 +178,8 @@ import java.util.List;
             "for example 2010-12-25</li><li>'previous_analysis' to compare to previous analysis</li><li>A version, for example 1.2</li></ul>",
         project = true,
         global = false,
-        defaultValue = CoreProperties.TIMEMACHINE_DEFAULT_PERIOD_4
+        defaultValue = CoreProperties.TIMEMACHINE_DEFAULT_PERIOD_4,
+        category = "Time Machine"
     ),
     @Property(
         key = "sonar.timemachine.period5",
@@ -170,7 +187,8 @@ import java.util.List;
         description = "See the property 'Period 4'",
         project = true,
         global = false,
-        defaultValue = CoreProperties.TIMEMACHINE_DEFAULT_PERIOD_5
+        defaultValue = CoreProperties.TIMEMACHINE_DEFAULT_PERIOD_5,
+        category = "Time Machine"
     )
 })
 public class CorePlugin extends SonarPlugin {
index 6695634552d2a35785d4914fa6da55c179749513..4d5541356c2c61c21e03c04a8f9b91e40119f5c0 100644 (file)
@@ -414,6 +414,16 @@ dashboard.edit_dashboard=Edit dashboard
 dashboard.update_dashboard=Update dashboard
 
 
+#------------------------------------------------------------------------------
+#
+# SETTINGS
+#
+#------------------------------------------------------------------------------
+settings.save_category=Save {0} settings
+settings.category.General=General
+
+
+
 #------------------------------------------------------------------------------
 #
 # WIDGETS
index b71fe2af2d428185db1754536f3af90190fcdd0c..02f38d19331076ad970c7bc6f4a8eb0b116bbfd3 100644 (file)
@@ -57,6 +57,11 @@ public @interface Property {
 
   String description() default "";
 
+  /**
+   * @since 2.11
+   */
+  String category() default "";
+
   /**
    * Is the property displayed in projet settings page ?
    */
index 79ae8f0ed597dafeb71cde6d375c797f775bd577..d5c5bceae455338916af0895549859b4bf6d7792 100644 (file)
@@ -71,6 +71,19 @@ class ProjectController < ApplicationController
     if !@project.project? && !@project.module?
       redirect_to :action => 'index', :id => params[:id]
     end
+
+    @category=params[:category] ||= 'General'
+    @properties_per_category={}
+    java_facade.getPluginsMetadata().each do |plugin|
+      properties=java_facade.getPluginProperties(plugin).select { |property|
+        (@project.module? && property.module()) || (@project.project? && property.project())
+      }
+      properties.each do |property|
+        category = (property.category().present? ? property.category() : plugin.name())
+        @properties_per_category[category]||=[]
+        @properties_per_category[category]<<property
+      end
+    end
   end
 
 
index 854c5f746db2244de26513bd868203f4eee13676..a936793ac294c16f3a7799c518bfacde10de8281 100644 (file)
@@ -21,25 +21,28 @@ class SettingsController < ApplicationController
 
   SECTION=Navigation::SECTION_CONFIGURATION
 
-  verify :method => :post, :only => ['update'], :redirect_to => { :action => :index }
+  verify :method => :post, :only => ['update'], :redirect_to => {:action => :index}
 
   def index
-    return access_denied unless is_admin?  
+    return access_denied unless is_admin?
+    load_properties()
+    @category ||= 'General'
   end
 
   def update
     if params[:resource_id]
       project=Project.by_key(params[:resource_id])
-      return access_denied unless is_admin?(project)
+      return access_denied unless (project && is_admin?(project))
       resource_id=project.id
     else
       return access_denied unless is_admin?
+      resource_id=nil
     end
 
-    plugins = java_facade.getPluginsMetadata()
-    plugins.each do |plugin|
-      properties=java_facade.getPluginProperties(plugin)
-      properties.each do |property|
+    load_properties()
+
+    if @category && @properties_per_category[@category]
+      @properties_per_category[@category].each do |property|
         value=params[property.key()]
         persisted_property = Property.find(:first, :conditions => {:prop_key=> property.key(), :resource_id => resource_id, :user_id => nil})
 
@@ -48,20 +51,34 @@ class SettingsController < ApplicationController
             Property.delete_all('prop_key' => property.key(), 'resource_id' => resource_id, 'user_id' => nil)
           elsif persisted_property.text_value != value.to_s
             persisted_property.text_value = value.to_s
-            persisted_property.save
+            persisted_property.save!
           end
-        elsif !value.blank? 
+        elsif !value.blank?
           Property.create(:prop_key => property.key(), :text_value => value.to_s, :resource_id => resource_id)
         end
       end
+      java_facade.reloadConfiguration()
+      flash[:notice] = 'Parameters updated'
     end
-    java_facade.reloadConfiguration()
 
-    flash[:notice] = 'Parameters updated.'
     if resource_id
-      redirect_to :controller => 'project', :action => 'settings', :id => resource_id
+      redirect_to :controller => 'project', :action => 'settings', :id => resource_id, :category => @category
     else
-      redirect_to :action => 'index'
+      redirect_to :controller => 'settings', :action => 'index', :category => @category
+    end
+  end
+
+  private
+
+  def load_properties
+    @category=params[:category]
+    @properties_per_category={}
+    java_facade.getPluginsMetadata().each do |plugin|
+      java_facade.getPluginProperties(plugin).select { |property| property.global }.each do |property|
+        category = (property.category().present? ? property.category() : plugin.name())
+        @properties_per_category[category]||=[]
+        @properties_per_category[category]<<property
+      end
     end
   end
 end
index 7e89d570273aa5856c416f2ffc2ddaa452281257..282a23c7627ff173bfdf2c3f0e114af0a3eb8044 100644 (file)
@@ -1,5 +1,5 @@
 <% if @snapshot.root? %>
-<h2>Delete project</h2>
+<h1>Delete project</h1>
 <div class="yui-g widget" id="widget_delete_project">
   <div class="warning">
     This operation can not be undone.
index 2e315bc82489226657516ac08b91242b3e5349ff..b2208db0f2b83d256d636a029dddbc9819a5ff63 100644 (file)
@@ -1,4 +1,4 @@
-<h2>Exclude sources from code analysis</h2>
+<h1>Exclude sources from code analysis</h1>
 <div class="yui-g widget" id="widget_exclusions">
 
 
index 4ae38c09f8d25658bf6b07b735646832faaa1617..8f79d83807ea2212e217d576a8c51c3c3b246848 100644 (file)
@@ -1,4 +1,4 @@
-<h2>Project links</h2>
+<h1>Project links</h1>
 <div class="yui-g widget" id="widget_links">
 
 <% form_for( 'set_links', :url => { :action => 'set_links', :project_id => @project.id } ) do |form|
index d0d7ad83c441ffc73a000658a1c654c79d9bbb12..59e305d9573c36cef37e5ef40cf7e01f4240516a 100644 (file)
 <style type="text/css">
-#plugins .plugin {
+  #plugins .plugin {
     padding: 5px;
     border: 1px solid #ddd;
     background-color: #fff;
-    }
-#plugins .plugin h2 {
-  margin-left: 10px;
-  font-size: 122%;
-  color: #333;
-}
-#plugins .plugin h3 {
-  margin-left: 5px;
-}
-#plugins .plugin p {
-    padding: 5px 5px;
-    }
-#plugins .plugin img {
-    padding: 5px 0 0 5px;
-    }
-</style>
-<div id="plugins">
-    <% form_tag :controller => :settings, :action => :update do
-      plugins = controller.java_facade.getPluginsMetadata().sort {|p1,p2| p1.getName() <=> p2.getName()}
-      plugin_properties={}
-      plugins.each do |plugin|
-        properties = controller.java_facade.getPluginProperties(plugin).select do |property|
-          (project && project.module? && property.module()) or (project && project.project? && property.project()) or (project.nil? && property.global)
-        end
-        plugin_properties[plugin]=properties
-      end
-
-    %>
-    <% if project %>
-        <input type="hidden" name="resource_id" value="<%= project.id -%>" ></input>
-    <% end %>
-        <table width="100%">
-            <tr>
-                <td width="1%" nowrap class="column first">
-                    <table class="data selector">
-                      <thead><tr><th>
-                      <span>Select plugin</span>
-                      </th></tr></thead>
-                        <tbody>
-                            <% plugins.each do |plugin|
-                                 if plugin_properties[plugin].empty?
-                                   # we display only plugins with properties
-                                   next
-                                 end
-                            %>
-                                <tr class="select <%= cycle('even', 'odd', :name => 'plugins') -%>" id="select_<%= plugin.getKey() -%>">
-                                    <td><a href="#" onclick="showPlugin('<%= plugin.getKey() -%>')"><%= h(plugin.getName()) -%></a></td>
-                                </tr>
-                            <% end %>
-                        </tbody>
-                    </table>
-                    <br/>
-                    <%= submit_tag('Save parameters') %>
-                </td>
-                <td class="column">
-
-                    <%
-                      values = Property.hash(project ? project.id : nil)
-                      plugins.each do |plugin|
-                        properties = plugin_properties[plugin]
-                    %>
-                        <div class="plugin" id="plugin_<%= plugin.getKey() -%>" style="display: none;">
-                            <table class="spaced">
-                            <% unless plugin.getDescription().blank? %>
-                            <tr><td class="odd">
-                              <p><%= plugin.getDescription() %></p>
-                            </td></tr>
-                            <% end %>
+  }
 
+  #plugins .plugin h2 {
+    margin-left: 10px;
+    font-size: 122%;
+    color: #333;
+  }
 
-                            <% properties.each do |property|
-                                 value= values[property.key()] || ''
-                                 css = cycle('even', 'odd', :name => plugin.getKey())
-                            %>
-                            <tr class="<%= css -%>">
-                              <td>
-                                <h3><%= property.name() %> <% if property.project() %><span class="note">[<%= property.key() -%>]</span><% end %></h3>
-                                <p><%= property.description() %></p>
-                                <p>
-                                <% span_id = "text_" + property.key().gsub('.', '_') %>
-                                <% textfield = text_field_tag property.key(), value, :size => '20' %>
-                                <% textfield += link_to_function(image_tag("zoom.png"), "replaceTextField('#{span_id}', '#{property.key()}')", :id => "toggle_text", :class => 'nolink') %>
-                                <% textarea = text_area_tag property.key(), value, :size => "100x10" %>
-                                <span id="<%= span_id %>"><%= (value.length < 50) ? textfield : textarea %></span>
+  #plugins .plugin h3 {
+    margin-left: 5px;
+  }
 
-                                <% unless property.defaultValue().blank? %>
-                                  <% if project.nil? %>
-                                    <span class="note">Default : <%= h property.defaultValue() -%></span>
-                                  <% else %>
-                                    <span class="note">Default : <%= h Property.value(property.key(), nil, property.defaultValue()) -%></span>
-                                  <% end %>
-                                <% end %>
-                                </p>
-                              </td>
-                            </tr>
-
-                            <% end %>
-                            </table>
-                        </div>
-                    <% end %>
-                </td>
-            </tr>
-        </table>
-    <% end %>
-</div>
+  #plugins .plugin p {
+    padding: 5px 5px;
+  }
 
+  #plugins .plugin img {
+    padding: 5px 0 0 5px;
+  }
+</style>
 <script type="text/javascript">
     function replaceTextField(span_id, key) {
       var text_field_value = $F(key);
       var text_area = '<textarea cols="100" id="' + key + '" name="' + key + '" rows="10">' + text_field_value + '</textarea>';
       $(span_id).replace(text_area);
     }
-    function showPlugin(id) {
-      $$('.plugin').each(function(element) {
-        element.hide();
-      });
-      $$('.select').each(function(element) {
-        element.removeClassName('selected');
-      });
-      $('plugin_' + id).show();
-      $('select_' + id).addClassName('selected');
-      return false;
-    }
-    showPlugin('core');
-</script>
\ No newline at end of file
+</script>
+<div id="plugins">
+  <table width="100%">
+    <tr>
+      <td width="1%" nowrap class="column first">
+        <table class="data selector">
+          <thead>
+          <tr>
+            <th>
+              <span>Category</span>
+            </th>
+          </tr>
+          </thead>
+          <tbody>
+          <%
+             @properties_per_category.keys.sort.each do |category|
+               unless @properties_per_category[category].empty?
+          %>
+              <tr class="select <%= cycle('even', 'odd', :name => 'category') -%> <%= 'selected' if @category==category -%>" id="select_<%= category -%>">
+                <td><%= link_to h(category), :overwrite_params => {:category => category} -%></td>
+              </tr>
+            <% end
+               end
+            %>
+          </tbody>
+        </table>
+        <br/>
+      </td>
+
+      <td class="column">
+        <% if @category
+          category_name = message("settings.category.#{@category}", :default => @category)
+        %>
+
+          <% form_tag :controller => :settings, :action => :update do %>
+            <%= hidden_field_tag('category', @category) -%>
+            <% if @project %>
+              <input type="hidden" name="resource_id" value="<%= @project.id -%>"/>
+            <% end %>
+            <table class="data marginbottom10">
+              <thead>
+              <tr>
+                <th>
+                  <span><%= h(category_name) -%></span>
+                </th>
+              </tr>
+              </thead>
+              <tbody>
+              <%
+                 if @properties_per_category[@category]
+                 @properties_per_category[@category].each do |property|
+                   value = Property.value(property.key(), (@project ? @project.id : nil), '')
+              %>
+                <tr class="<%= cycle('even', 'odd', :name => 'properties') -%>">
+                  <td style="padding:  10px">
+                    <h3>
+                      <%= h(property.name()) -%>
+                      <% if property.project() %>
+                        <br/><span class="note"><%= property.key() -%></span>
+                      <% end %>
+                    </h3>
+                    <% if property.description.present? %>
+                      <p class="marginbottom10"><%= property.description -%></p>
+                    <% end %>
+                    <p>
+                      <% span_id = "text_" + property.key().gsub('.', '_') %>
+                      <% textfield = text_field_tag property.key(), value, :size => '20' %>
+                      <% textfield += link_to_function(image_tag("zoom.png"), "replaceTextField('#{span_id}', '#{property.key()}')", :id => "toggle_text", :class => 'nolink') %>
+                      <% textarea = text_area_tag property.key(), value, :size => "100x10" %>
+                      <span id="<%= span_id %>"><%= (value.length < 50) ? textfield : textarea %></span>
+
+                      <% unless property.defaultValue().blank? %>
+                        <% if @project %>
+                          <span class="note">Default : <%= h Property.value(property.key(), nil, property.defaultValue()) -%></span>
+                        <% else %>
+                          <span class="note">Default : <%= h property.defaultValue() -%></span>
+                        <% end %>
+                      <% end %>
+                    </p>
+                  </td>
+                </tr>
+              <%   end
+                end
+              %>
+              </tbody>
+            </table>
+            <% save_message=message('settings.save_category', :params => [category_name]) %>
+            <%= submit_tag(save_message, :disable_with => save_message, :id => 'save') -%>
+          <% end %>
+        <% end %>
+      </td>
+    </tr>
+  </table>
+</div>