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,
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,
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,
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",
"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",
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",
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",
"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",
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 {
dashboard.update_dashboard=Update dashboard
+#------------------------------------------------------------------------------
+#
+# SETTINGS
+#
+#------------------------------------------------------------------------------
+settings.save_category=Save {0} settings
+settings.category.General=General
+
+
+
#------------------------------------------------------------------------------
#
# WIDGETS
String description() default "";
+ /**
+ * @since 2.11
+ */
+ String category() default "";
+
/**
* Is the property displayed in projet settings page ?
*/
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
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})
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
<% 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.
-<h2>Exclude sources from code analysis</h2>
+<h1>Exclude sources from code analysis</h1>
<div class="yui-g widget" id="widget_exclusions">
-<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|
<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>