]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-3034 API: default value of WidgetProperty is not injected in Ruby widgets
authorSimon Brandhof <simon.brandhof@gmail.com>
Thu, 15 Dec 2011 15:28:55 +0000 (16:28 +0100)
committerSimon Brandhof <simon.brandhof@gmail.com>
Thu, 15 Dec 2011 15:28:55 +0000 (16:28 +0100)
The column WIDGET_PROPERTIES.VALUE_TYPE is removed because it duplicates the Java extensions.

29 files changed:
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/HotspotMostViolatedRulesWidget.java
plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/hotspots/hotspot_metric.html.erb
plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/hotspots/hotspot_most_violated_resources.html.erb
plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/hotspots/hotspot_most_violated_rules.html.erb
plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/reviews/false_positive_reviews.html.erb
plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/reviews/my_reviews.html.erb
plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/reviews/project_reviews.html.erb
plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/time_machine.html.erb
plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/timeline.html.erb
sonar-core/src/main/java/org/sonar/jpa/entity/SchemaMigration.java
sonar-core/src/main/java/org/sonar/persistence/dashboard/WidgetPropertyDto.java
sonar-core/src/main/resources/org/sonar/persistence/dashboard/WidgetPropertyMapper-oracle.xml
sonar-core/src/main/resources/org/sonar/persistence/dashboard/WidgetPropertyMapper.xml
sonar-core/src/main/resources/org/sonar/persistence/rows-derby.sql
sonar-core/src/main/resources/org/sonar/persistence/schema-derby.ddl
sonar-core/src/test/java/org/sonar/persistence/dashboard/DashboardDaoTest.java
sonar-core/src/test/resources/org/sonar/persistence/dashboard/DashboardDaoTest/shouldInsert-result.xml
sonar-core/src/test/resources/org/sonar/persistence/dashboard/DashboardDaoTest/shouldInsertWithNullableColumns-result.xml
sonar-server/src/main/java/org/sonar/server/ui/ViewProxy.java
sonar-server/src/main/webapp/WEB-INF/app/controllers/dashboard_controller.rb
sonar-server/src/main/webapp/WEB-INF/app/models/widget.rb
sonar-server/src/main/webapp/WEB-INF/app/models/widget_property.rb
sonar-server/src/main/webapp/WEB-INF/app/views/dashboard/_configure_widget.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/dashboard/_widget.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/dashboard/_widget_definition.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/dashboard/_widget_properties.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/dashboard/configure.html.erb
sonar-server/src/main/webapp/WEB-INF/db/migrate/237_delete_value_type_from_widget_properties.rb [new file with mode: 0644]
sonar-server/src/test/java/org/sonar/server/ui/ViewProxyTest.java

index fbd14931150ff5963ccff320cba0bbd4304c684d..05f0bdc845e7fe75fdd9f04a32438ed72c944cef 100644 (file)
@@ -21,12 +21,12 @@ package org.sonar.plugins.core.widgets;
 
 import org.sonar.api.web.*;
 
-@WidgetCategory({"Hotspots"})
+@WidgetCategory("Hotspots")
 @WidgetProperties(
-    {
-        @WidgetProperty(key = "numberOfLines", type = WidgetPropertyType.INTEGER, defaultValue = "5"),
-        @WidgetProperty(key = "defaultSeverity", type = WidgetPropertyType.STRING, description = "Values: BLOCKER, CRITICAL, MAJOR, MINOR, INFO")
-    }
+  {
+    @WidgetProperty(key = "numberOfLines", type = WidgetPropertyType.INTEGER, defaultValue = "5"),
+    @WidgetProperty(key = "defaultSeverity", type = WidgetPropertyType.STRING, description = "Values: BLOCKER, CRITICAL, MAJOR, MINOR, INFO")
+  }
 )
 public class HotspotMostViolatedRulesWidget extends AbstractRubyTemplate implements RubyRailsWidget {
   public String getId() {
index 1ba4c65a7b15e7206a5a10ecf1d00c82319fadc8..7c397e1366b7ff866e0d5ccba5101d901c88fcdb 100644 (file)
@@ -1,7 +1,7 @@
 <%
    metric = widget_properties["metric"]
    metric = Metric.by_key('ncloc') unless metric
-   limit = widget_properties["numberOfLines"] || 5
+   limit = widget_properties["numberOfLines"]
    title = widget_properties["title"]
    title = message('widget.hotspot_metric.hotspots_by_x', :params => metric.short_name) if title.blank?
 
index 3f054649615fce3715e397076c001306197739d7..d69c7fa7dc604eb873b39679c5d119fe635faecf 100644 (file)
@@ -1,32 +1,31 @@
 <%
-  limit = widget_properties["numberOfLines"] || 5
-  
-  metric = Metric.by_key('weighted_violations')
-  
-  snapshots_conditions=["snapshots.scope = 'FIL'", "snapshots.islast=:islast", "snapshots.status = 'P'"]
-  snapshots_values={:islast => true}
-  snapshots_conditions << "(snapshots.qualifier = 'CLA' OR snapshots.qualifier = 'FIL' OR snapshots.qualifier = 'TRK')"
-  snapshots_conditions << '(snapshots.id=:sid OR (snapshots.root_snapshot_id=:root_sid AND snapshots.path LIKE :path))'
-  snapshots_values[:sid]=@snapshot.id
-  snapshots_values[:root_sid] = (@snapshot.root_snapshot_id || @snapshot.id)
-  snapshots_values[:path]="#{@snapshot.path}#{@snapshot.id}.%"
-      
-  measures_conditions = ["project_measures.rule_id IS NULL", "project_measures.characteristic_id IS NULL"]
-  measures_values = {}
-  measures_conditions << "project_measures.metric_id = :m_id"
-  measures_values[:m_id] = metric.id
-  
-  measures=ProjectMeasure.find(:all,
-                               :joins => :snapshot, 
-                               :conditions => [ (snapshots_conditions + measures_conditions).join(' AND '), snapshots_values.merge(measures_values)],
-                               :order => "project_measures.value #{'DESC' if metric.direction<0}",
-                               :limit => limit)
-  
-  snapshots=Snapshot.find(measures.map {|m| m.snapshot_id}, :include => 'project')
-  snapshots_by_id = {}
-  snapshots.each do |s|
-    snapshots_by_id[s.id]=s
-  end  
+   limit = widget_properties["numberOfLines"]
+   metric = Metric.by_key('weighted_violations')
+
+   snapshots_conditions=["snapshots.scope = 'FIL'", "snapshots.islast=:islast", "snapshots.status = 'P'"]
+   snapshots_values={:islast => true}
+   snapshots_conditions << "(snapshots.qualifier = 'CLA' OR snapshots.qualifier = 'FIL' OR snapshots.qualifier = 'TRK')"
+   snapshots_conditions << '(snapshots.id=:sid OR (snapshots.root_snapshot_id=:root_sid AND snapshots.path LIKE :path))'
+   snapshots_values[:sid]=@snapshot.id
+   snapshots_values[:root_sid] = (@snapshot.root_snapshot_id || @snapshot.id)
+   snapshots_values[:path]="#{@snapshot.path}#{@snapshot.id}.%"
+
+   measures_conditions = ["project_measures.rule_id IS NULL", "project_measures.characteristic_id IS NULL"]
+   measures_values = {}
+   measures_conditions << "project_measures.metric_id = :m_id"
+   measures_values[:m_id] = metric.id
+
+   measures=ProjectMeasure.find(:all,
+                                :joins => :snapshot,
+                                :conditions => [(snapshots_conditions + measures_conditions).join(' AND '), snapshots_values.merge(measures_values)],
+                                :order => "project_measures.value #{'DESC' if metric.direction<0}",
+                                :limit => limit)
+
+   snapshots=Snapshot.find(measures.map { |m| m.snapshot_id }, :include => 'project')
+   snapshots_by_id = {}
+   snapshots.each do |s|
+     snapshots_by_id[s.id]=s
+   end
 %>
 
 <div class="line-block">
 </div>
 
 <table id="most-violated-resources-<%= widget.id -%>" class="data">
-  <thead><tr><th colspan="11"></th></tr></thead>
+  <thead>
+  <tr>
+    <th colspan="11"></th>
+  </tr>
+  </thead>
   <tbody>
-<%
-  measures.each do |measure|
-    resource = snapshots_by_id[measure.snapshot_id].resource
-    violations_per_severity={}
-    measure.text_value.split(';').each do |part|
-      fields=part.split('=')
-      violations_per_severity[fields[0]]=fields[1]
-    end
-%>
-    <tr class="<%= cycle 'even','odd', :name => ('hotspot_most_violated_resources' + widget.id.to_s) -%>">
+  <%
+     measures.each do |measure|
+       resource = snapshots_by_id[measure.snapshot_id].resource
+       violations_per_severity={}
+       measure.text_value.split(';').each do |part|
+         fields=part.split('=')
+         violations_per_severity[fields[0]]=fields[1]
+       end
+  %>
+    <tr class="<%= cycle 'even', 'odd', :name => ('hotspot_most_violated_resources' + widget.id.to_s) -%>">
       <td>
         <%= link_to_resource(resource, resource.name, {:tab => :violations}) -%>
       </td>
       </td>
       <td class="small left">
         <%= violations_per_severity["INFO"] ? violations_per_severity["INFO"].to_s : "0" -%>
-      </td>    
+      </td>
     </tr>
-<%
-  end
-%>
+  <%
+     end
+  %>
   </tbody>
 </table>
\ No newline at end of file
index 0ef8719bb34b4092ff08cee49f02cb065dd45355..988f6c606c6c7631181689705e1988409d0d3f73 100644 (file)
@@ -1,5 +1,5 @@
 <%
-   limit = widget_properties["numberOfLines"] || 5
+   limit = widget_properties["numberOfLines"]
    metric_prefix = dashboard_configuration.selected_period? ? 'new_' : ''
    value_column = (dashboard_configuration.selected_period? ? "variation_value_#{dashboard_configuration.period_index}" : 'value')
    measures_by_severity = {}
@@ -16,7 +16,7 @@
    end
    measures_by_severity['']=all_measures.sort { |a, b| b.send(value_column) <=> a.send(value_column) }[0...limit]
 
-   default_severity = widget_properties['defaultSeverity']||''
+   default_severity = widget_properties['defaultSeverity']
    default_severity = '' unless Severity::KEYS.include?(default_severity)
 %>
 
index 296436c8a12af55518233d8cec60911e7b951a04..800b5b1b7f7f586e10a46ca040174c7ff7039cf6 100644 (file)
@@ -1,31 +1,31 @@
-<% 
-  if has_role?(:user, @project)
-    limit = widget_properties["numberOfLines"].to_i == 0 ? 5 : widget_properties["numberOfLines"].to_i
-    
-    if @dashboard_configuration.selected_period?
-      from_date = @dashboard_configuration.from_datetime
-      to_date = DateTime.now
-    end
+<%
+   if has_role?(:user, @project)
+     limit = widget_properties["numberOfLines"]
+
+     if @dashboard_configuration.selected_period?
+       from_date = @dashboard_configuration.from_datetime
+       to_date = DateTime.now
+     end
 %>
 
-<div class="line-block">
-  <div style="float:right">
-    <a href="<%= url_for :controller => 'reviews', :action => 'index', :projects => [@project.id], :false_positives => 'only',
-                         :assignee_login => '', :statuses => [''], :from => from_date, :to => to_date -%>">
-      <%= message('widgets.more') -%>
-    </a>
+  <div class="line-block">
+    <div style="float:right">
+      <a href="<%= url_for :controller => 'reviews', :action => 'index', :projects => [@project.id], :false_positives => 'only',
+                           :assignee_login => '', :statuses => [''], :from => from_date, :to => to_date -%>">
+        <%= message('widgets.more') -%>
+      </a>
+    </div>
+    <h3><%= message('widget.false_positive_reviews.name') -%></h3>
   </div>
-  <h3><%= message('widget.false_positive_reviews.name') -%></h3>
-</div>
 
-<div id="reviews-widget-<%= widget.id -%>">
-  <%= render :partial => 'project/widgets/reviews/reviews_list', 
-             :locals => {:assignee_login => '', 
-                         :project_key => @project.key,
-                         :statuses => 'RESOLVED',
-                         :resolution => 'FALSE-POSITIVE',
-                         :limit => limit,
-                         :widget_id => widget.id.to_s} %>
-</div>
+  <div id="reviews-widget-<%= widget.id -%>">
+    <%= render :partial => 'project/widgets/reviews/reviews_list',
+               :locals => {:assignee_login => '',
+                           :project_key => @project.key,
+                           :statuses => 'RESOLVED',
+                           :resolution => 'FALSE-POSITIVE',
+                           :limit => limit,
+                           :widget_id => widget.id.to_s} %>
+  </div>
 
 <% end %>
index e467103072e8385bf4348900a2e9b226427d8e41..8212be3f2ed29dd075c0aad511d5c506df974cbe 100644 (file)
@@ -1,30 +1,30 @@
-<% 
-  if current_user && has_role?(:user, @project)
-    limit = widget_properties["numberOfLines"].to_i == 0 ? 5 : widget_properties["numberOfLines"].to_i
-    
-    if @dashboard_configuration.selected_period?
-      from_date = @dashboard_configuration.from_datetime
-      to_date = DateTime.now
-    end
+<%
+   if current_user && has_role?(:user, @project)
+     limit = widget_properties["numberOfLines"]
+
+     if @dashboard_configuration.selected_period?
+       from_date = @dashboard_configuration.from_datetime
+       to_date = DateTime.now
+     end
 %>
 
-<div class="line-block">
-  <div style="float:right">
-    <a href="<%= url_for :controller => 'reviews', :action => 'index', :projects => [@project.id], :from => from_date, :to => to_date -%>">
-      <%= message('widgets.more') -%>
-    </a>
+  <div class="line-block">
+    <div style="float:right">
+      <a href="<%= url_for :controller => 'reviews', :action => 'index', :projects => [@project.id], :from => from_date, :to => to_date -%>">
+        <%= message('widgets.more') -%>
+      </a>
+    </div>
+    <h3><%= message('widget.my_reviews.name') -%></h3>
   </div>
-  <h3><%= message('widget.my_reviews.name') -%></h3>
-</div>
 
-<div id="reviews-widget-<%= widget.id -%>">
-  <%= render :partial => 'project/widgets/reviews/reviews_list', 
-             :locals => {:assignee_login => current_user.login, 
-                         :project_key => @project.key,
-                         :statuses => 'OPEN,REOPENED',
-                         :resolution => '',
-                         :limit => limit,
-                         :widget_id => widget.id.to_s} %>
-</div>
+  <div id="reviews-widget-<%= widget.id -%>">
+    <%= render :partial => 'project/widgets/reviews/reviews_list',
+               :locals => {:assignee_login => current_user.login,
+                           :project_key => @project.key,
+                           :statuses => 'OPEN,REOPENED',
+                           :resolution => '',
+                           :limit => limit,
+                           :widget_id => widget.id.to_s} %>
+  </div>
 
 <% end %>
\ No newline at end of file
index 2d89c60c43e7f29c736aa3a32ddd741eb5be9b93..ae226d7c49769fb6e8eea4dbba4fbe669229b90e 100644 (file)
@@ -1,6 +1,6 @@
 <%
    if has_role?(:user, @project)
-     limit = widget_properties["numberOfLines"].to_i == 0 ? 5 : widget_properties["numberOfLines"].to_i
+     limit = widget_properties["numberOfLines"]
 
      from_date=nil
      to_date=nil
index f580f788a06d664e02e8243483df6ce5a48d1be1..c2677939d40be1ac7addb101a04158c138cee741 100644 (file)
 <%
-  # Retrieve widget settings
-  metric_ids = []
-  (1..10).each do |index|
-    metric=widget_properties["metric#{index}"]
-    if metric
-      metric_ids << metric.id
-    end
-  end
-  if metric_ids.empty?
-    # No metric has been selected, it's the first time the widget is displayed: 'ncloc' is the default metric
-    ncloc = Metric.find(:first, :conditions => "name = 'ncloc'")
-    metric_ids << ncloc.id
-  end
-  numberOfColumns = widget_properties["numberOfColumns"].to_i == 0 ? 4 : widget_properties["numberOfColumns"].to_i
-  
-  # Retrieve the measures for each metric on each snapshot
-  options = {}
-  from_date = dashboard_configuration.from_datetime
-  if from_date
-    options[:from] = from_date
-  end
-  snapshots=Snapshot.for_timemachine_widget(@resource, numberOfColumns, options)
-  sids = snapshots.collect{|s| s.id}.uniq
-  measures=ProjectMeasure.find(:all, 
-                               :conditions => ["snapshot_id IN (:snapshot_id) AND metric_id IN (:metric_id) AND rule_id IS NULL AND characteristic_id IS NULL", 
-                                               {:snapshot_id => sids, :metric_id => metric_ids}]
-                               )
+   # Retrieve widget settings
+   metric_ids = []
+   (1..10).each do |index|
+     metric=widget_properties["metric#{index}"]
+     if metric
+       metric_ids << metric.id
+     end
+   end
+   if metric_ids.empty?
+     # No metric has been selected, it's the first time the widget is displayed: 'ncloc' is the default metric
+     ncloc = Metric.find(:first, :conditions => "name = 'ncloc'")
+     metric_ids << ncloc.id
+   end
+   number_of_columns = widget_properties["numberOfColumns"]
 
-  # And prepare the rows to display
-  snapshot_by_id={}
-  snapshots.each do |s|
-    snapshot_by_id[s.id]=s
-  end
-  rows_by_metric_id={}
-  measures.each do |measure|
-    next unless measure.metric
+   # Retrieve the measures for each metric on each snapshot
+   options = {}
+   from_date = dashboard_configuration.from_datetime
+   if from_date
+     options[:from] = from_date
+   end
+   snapshots=Snapshot.for_timemachine_widget(@resource, number_of_columns, options)
+   sids = snapshots.collect { |s| s.id }.uniq
+   measures=ProjectMeasure.find(:all,
+                                :conditions => ["snapshot_id IN (:snapshot_id) AND metric_id IN (:metric_id) AND rule_id IS NULL AND characteristic_id IS NULL",
+                                                {:snapshot_id => sids, :metric_id => metric_ids}]
+   )
 
-    if measure.metric.timemachine? && (measure.value || measure.text_value)
-      row=rows_by_metric_id[measure.metric_id]
-      unless row
-        row=Sonar::TimemachineRow.new(measure.metric)
-        rows_by_metric_id[measure.metric_id]=row
-      end
+   # And prepare the rows to display
+   snapshot_by_id={}
+   snapshots.each do |s|
+     snapshot_by_id[s.id]=s
+   end
+   rows_by_metric_id={}
+   measures.each do |measure|
+     next unless measure.metric
 
-      #optimization : avoid eager loading of snapshots
-      measure.snapshot=snapshot_by_id[measure.snapshot_id]
-      row.add_measure(measure)
-    end
-  end
-  
-  # Create the list of rows to display in the same order as defined by the user
-  rows=[]
-  metric_ids.each do |metric_id|
-    row = rows_by_metric_id[metric_id]
-    if row
-      rows<<row
-    end
-  end
-  
-  # Should display the sparkline?
-  displaySparkLine = widget_properties["displaySparkLine"] if snapshot_by_id.size > 1
+     if measure.metric.timemachine? && (measure.value || measure.text_value)
+       row=rows_by_metric_id[measure.metric_id]
+       unless row
+         row=Sonar::TimemachineRow.new(measure.metric)
+         rows_by_metric_id[measure.metric_id]=row
+       end
+
+       #optimization : avoid eager loading of snapshots
+       measure.snapshot=snapshot_by_id[measure.snapshot_id]
+       row.add_measure(measure)
+     end
+   end
+
+   # Create the list of rows to display in the same order as defined by the user
+   rows=[]
+   metric_ids.each do |metric_id|
+     row = rows_by_metric_id[metric_id]
+     if row
+       rows<<row
+     end
+   end
+
+   # Should display the sparkline?
+   displaySparkLine = widget_properties["displaySparkLine"] if snapshot_by_id.size > 1
 %>
 
 <div class="widget-matrix">
 
-<table class="data">
+  <table class="data">
 
-  <thead>
+    <thead>
     <tr>
-      <th> </th>
-      <% 
-        snapshots.each do |snapshot| 
-          event = snapshot.event('Version')
+      <th></th>
+      <%
+         snapshots.each do |snapshot|
+           event = snapshot.event('Version')
       %>
         <th nowrap="nowrap" style="vertical-align:top">
-            <%= l snapshot.created_at.to_date -%>
-            <br/>
-            <%= event.name unless event==nil -%>
+          <%= l snapshot.created_at.to_date -%>
+          <br/>
+          <%= event.name unless event==nil -%>
         </th>
       <% end %>
       <% if displaySparkLine %>
-      <th> </th>
+        <th></th>
       <% end %>
-  </tr>
-  </thead>
+    </tr>
+    </thead>
 
-  <tbody>
-    <%
-      rows.select{|row| row.metric.val_type != Metric::VALUE_TYPE_DISTRIB}.each do |row|
-    %>
-    <tr class="<%= cycle 'even','odd', :name => ('time_machine' + widget.id.to_s) -%>">
-      <td width="1%" nowrap="nowrap" class="left text">
-        <%= row.metric.short_name %>
-      </td>
-    <% 
-      snapshots.each do |snapshot|
-        measure=row.measure(snapshot)
-    %>
-      <td width="1%" nowrap="nowrap" class="right"><%= format_measure(measure, :skip_span_id => true) %></td>
-    <% end %>
+    <tbody>
     <%
-      sparkline_url=row.sparkline_url
-      if displaySparkLine && sparkline_url
+       rows.select { |row| row.metric.val_type != Metric::VALUE_TYPE_DISTRIB }.each do |row|
     %>
-      <td width="1%" >
-        <%= image_tag(sparkline_url) %>
-      </td>
-    <% end %>
-    </tr>
+      <tr class="<%= cycle 'even', 'odd', :name => ('time_machine' + widget.id.to_s) -%>">
+        <td width="1%" nowrap="nowrap" class="left text">
+          <%= row.metric.short_name %>
+        </td>
+        <%
+           snapshots.each do |snapshot|
+             measure=row.measure(snapshot)
+        %>
+          <td width="1%" nowrap="nowrap" class="right"><%= format_measure(measure, :skip_span_id => true) %></td>
+        <% end %>
+        <%
+           sparkline_url=row.sparkline_url
+           if displaySparkLine && sparkline_url
+        %>
+          <td width="1%">
+            <%= image_tag(sparkline_url) %>
+          </td>
+        <% end %>
+      </tr>
     <% end %>
-  </tbody>
+    </tbody>
 
-</table>
+  </table>
 
 </div>
\ No newline at end of file
index 5d8dab0b8962d434b7fe2cbdab1f78c1b28d8300..7a4d6b773c7a0cbc1b0b00cc00486a1f34351c7e 100644 (file)
 <%
-  # Retrieve widget settings
-  metric_data_map = {}
-  metric_name_map = {}
-  (1..3).each do |index|
-    metric=widget_properties["metric#{index}"]
-    if metric
-      metric_data_map[metric.id] = []
-      metric_name_map[metric.id] = metric.short_name
-    end
-  end
-  if metric_data_map.empty?
-    # No metric has been selected, it's the first time the widget is displayed: 'ncloc' is the default metric
-    ncloc = Metric.find(:first, :conditions => "name = 'ncloc'")
-    metric_data_map[ncloc.id] = []
-    metric_name_map[ncloc.id] = message('metric.ncloc.name')
-  end
-  chartHeight = widget_properties["chartHeight"].to_i == 0 ? "null" : widget_properties["chartHeight"]
-  
-  # Retrieve metric trend information
-  options = {}
-  from_date = dashboard_configuration.from_datetime
-  if from_date
-    options[:from] = from_date
-  end
-  metric_count_per_snapshot_id = {}
-  TrendsChart.time_machine_measures(@resource, metric_data_map.keys, options).each()  do |trend_item|
-    sid = trend_item["sid"]
-    if metric_count_per_snapshot_id[sid]
-      metric_count_per_snapshot_id[sid] += 1
-    else
-      metric_count_per_snapshot_id[sid] = 1
-    end
-    metric_data_map[trend_item["metric_id"].to_i] << {:date => trend_item["created_at"], :value => trend_item["value"], :sid => trend_item["sid"]}
-  end
+   # Retrieve widget settings
+   metric_data_map = {}
+   metric_name_map = {}
+   (1..3).each do |index|
+     metric=widget_properties["metric#{index}"]
+     if metric
+       metric_data_map[metric.id] = []
+       metric_name_map[metric.id] = metric.short_name
+     end
+   end
+   if metric_data_map.empty?
+     # No metric has been selected, it's the first time the widget is displayed: 'ncloc' is the default metric
+     ncloc = Metric.find(:first, :conditions => "name = 'ncloc'")
+     metric_data_map[ncloc.id] = []
+     metric_name_map[ncloc.id] = message('metric.ncloc.name')
+   end
+   chartHeight = widget_properties["chartHeight"]
+
+   # Retrieve metric trend information
+   options = {}
+   from_date = dashboard_configuration.from_datetime
+   if from_date
+     options[:from] = from_date
+   end
+   metric_count_per_snapshot_id = {}
+   TrendsChart.time_machine_measures(@resource, metric_data_map.keys, options).each() do |trend_item|
+     sid = trend_item["sid"]
+     if metric_count_per_snapshot_id[sid]
+       metric_count_per_snapshot_id[sid] += 1
+     else
+       metric_count_per_snapshot_id[sid] = 1
+     end
+     metric_data_map[trend_item["metric_id"].to_i] << {:date => trend_item["created_at"], :value => trend_item["value"], :sid => trend_item["sid"]}
+   end
+
+   # Create JS structures to print out in the HTML page
+   js_data = "["
+   js_snapshots = "["
+   js_metrics = "["
+   total_number_of_metrics = metric_name_map.keys.size()
+   metric_data_map.keys.each_with_index() do |metric_id, index|
+     unless metric_data_map[metric_id].empty?
+       js_metrics += "\"" + metric_name_map[metric_id] + "\","
+       js_data += "["
+       metric_data_map[metric_id].each() do |metric_data|
+         # for every metric value, we need to check that the corresponding snapshot has values for each metric (if not, Protovis won't be able to display)
+         if metric_count_per_snapshot_id[metric_data[:sid]]==total_number_of_metrics
+           m_date = metric_data[:date]
+           # Only Oracle returns a Time object, so let's parse this string if it's not a Time instance
+           m_date = Time.parse(metric_data[:date]) unless m_date.is_a? Time
+           m_value = sprintf("%0.02f", metric_data[:value])
+           m_value_localized = (m_value.end_with? '.00') ? number_with_precision(metric_data[:value], :precision => 0).to_s : number_with_precision(metric_data[:value], :precision => 2).to_s
+           js_data += "{x:d("
+           js_data += m_date.year.to_s
+           js_data += ","
+           # Need to decrease by 1 the month as the JS Date object start months at 0 (= January)
+           js_data += (m_date.month - 1).to_s
+           js_data += ","
+           js_data += m_date.day.to_s
+           js_data += ","
+           js_data += m_date.hour.to_s
+           js_data += ","
+           js_data += m_date.min.to_s
+           js_data += ","
+           js_data += m_date.sec.to_s
+           js_data += "),y:"
+           js_data += m_value
+           js_data += ",yl:\""
+           js_data += m_value_localized
+           js_data += "\"},"
+           if index == 0
+             # we fill the js_snapshots array (no need to do this more than once)
+             js_snapshots += "{sid:"
+             js_snapshots += metric_data[:sid].to_s
+             js_snapshots += ",d:\""
+             js_snapshots += human_short_date m_date
+             js_snapshots += "\"},"
+           end
+         end
+       end
+       js_data = js_data.chomp(',') + "],"
+     end
+   end
+   js_data = js_data.chomp(',') + "]"
+   js_snapshots = js_snapshots.chomp(',') + "]"
+   js_metrics = js_metrics.chomp(',') + "]"
+
+   # Prepare also event structure if required
+   unless widget_properties["hideEvents"]
+     events = {}
+     unless from_date
+       # find the oldest date
+       metric_data_map.values.each() do |metric_data_array|
+         first_date = metric_data_array[0][:date]
+         # Only Oracle returns a Time object, so let's parse this string if it's not a Time instance
+         first_date = Time.parse(metric_data_array[0][:date]) unless first_date.is_a? Time
+         from_date = first_date if !from_date || from_date > first_date
+       end
+     end
+     Event.find(:all, :conditions => ["resource_id=? AND event_date>=?", @resource.id, from_date], :order => 'event_date').each() do |event|
+       if events[event.event_date]
+         events[event.event_date] << event
+       else
+         date_entry = [event]
+         events[event.event_date] = date_entry
+       end
+     end
+     js_events = "["
+     events.keys().sort.each() do |e_date|
+       e_details = events[e_date]
+       js_events += "{sid:"
+       js_events += e_details[0].snapshot_id.to_s
+       js_events += ",d:d("
+       js_events += e_date.year.to_s
+       js_events += ","
+       # Need to decrease by 1 the month as the JS Date object start months at 0 (= January)
+       js_events += (e_date.month - 1).to_s
+       js_events += ","
+       js_events += e_date.day.to_s
+       js_events += ","
+       js_events += e_date.hour.to_s
+       js_events += ","
+       js_events += e_date.min.to_s
+       js_events += ","
+       js_events += e_date.sec.to_s
+       js_events += "),l:["
+       e_details.each() do |e|
+         js_events += "{n:\""
+         js_events += e.name
+         js_events += "\"},"
+       end
+       js_events = js_events.chomp(',') + "]},"
+     end
+     js_events = js_events.chomp(',') + "]"
+   end
 
-  # Create JS structures to print out in the HTML page 
-  js_data = "["
-  js_snapshots = "["
-  js_metrics = "["
-  total_number_of_metrics = metric_name_map.keys.size()
-  metric_data_map.keys.each_with_index() do |metric_id, index|
-    unless metric_data_map[metric_id].empty?
-      js_metrics += "\"" + metric_name_map[metric_id] + "\","
-      js_data += "["
-      metric_data_map[metric_id].each() do |metric_data|
-        # for every metric value, we need to check that the corresponding snapshot has values for each metric (if not, Protovis won't be able to display)
-        if metric_count_per_snapshot_id[metric_data[:sid]]==total_number_of_metrics
-          m_date = metric_data[:date]
-          # Only Oracle returns a Time object, so let's parse this string if it's not a Time instance
-          m_date = Time.parse(metric_data[:date]) unless m_date.is_a? Time
-          m_value = sprintf( "%0.02f", metric_data[:value])
-          m_value_localized = (m_value.end_with? '.00') ? number_with_precision(metric_data[:value], :precision => 0).to_s : number_with_precision(metric_data[:value], :precision => 2).to_s
-          js_data += "{x:d("
-          js_data += m_date.year.to_s
-          js_data += ","
-          # Need to decrease by 1 the month as the JS Date object start months at 0 (= January)
-          js_data += (m_date.month - 1).to_s
-          js_data += ","
-          js_data += m_date.day.to_s
-          js_data += ","
-          js_data += m_date.hour.to_s
-          js_data += ","
-          js_data += m_date.min.to_s
-          js_data += ","
-          js_data += m_date.sec.to_s
-          js_data += "),y:" 
-          js_data += m_value
-          js_data +=  ",yl:\""
-          js_data += m_value_localized
-          js_data +=  "\"},"
-          if index == 0
-            # we fill the js_snapshots array (no need to do this more than once)
-            js_snapshots += "{sid:"
-            js_snapshots += metric_data[:sid].to_s
-            js_snapshots += ",d:\""
-            js_snapshots += human_short_date m_date
-            js_snapshots += "\"},"
-          end
-        end
-      end
-      js_data = js_data.chomp(',') + "],"
-    end
-  end
-  js_data = js_data.chomp(',') + "]"
-  js_snapshots = js_snapshots.chomp(',') + "]"
-  js_metrics = js_metrics.chomp(',') + "]"
-  
-  # Prepare also event structure if required
-  unless widget_properties["hideEvents"]
-    events = {}
-    unless from_date
-      # find the oldest date
-      metric_data_map.values.each() do |metric_data_array|
-        first_date = metric_data_array[0][:date]
-        # Only Oracle returns a Time object, so let's parse this string if it's not a Time instance
-        first_date = Time.parse(metric_data_array[0][:date]) unless first_date.is_a? Time
-        from_date = first_date if !from_date || from_date > first_date  
-      end
-    end
-    Event.find(:all, :conditions => ["resource_id=? AND event_date>=?", @resource.id, from_date], :order => 'event_date').each() do |event|
-      if events[event.event_date]
-        events[event.event_date] << event
-      else
-        date_entry = [event]
-        events[event.event_date] = date_entry
-      end
-    end
-    js_events = "["
-    events.keys().sort.each() do |e_date|
-      e_details = events[e_date]
-      js_events += "{sid:"
-      js_events += e_details[0].snapshot_id.to_s
-      js_events += ",d:d("
-      js_events += e_date.year.to_s
-      js_events += ","
-      # Need to decrease by 1 the month as the JS Date object start months at 0 (= January)
-      js_events += (e_date.month - 1).to_s
-      js_events += ","
-      js_events += e_date.day.to_s
-      js_events += ","
-      js_events += e_date.hour.to_s
-      js_events += ","
-      js_events += e_date.min.to_s
-      js_events += ","
-      js_events += e_date.sec.to_s
-      js_events += "),l:["
-      e_details.each() do |e|
-        js_events += "{n:\""
-        js_events += e.name
-        js_events += "\"},"
-      end 
-      js_events = js_events.chomp(',') + "]},"
-    end
-    js_events = js_events.chomp(',') + "]"
-  end
-    
 %>
 
 <% if widget_properties["chartTitle"] %>
-<h3 style="text-align: center; margin-bottom: 10px"><%= h(widget_properties["chartTitle"]) -%></h3>
+  <h3 style="text-align: center; margin-bottom: 10px"><%= h(widget_properties["chartTitle"]) -%></h3>
 <% end %>
 
 
 <% if metric_data_map.values[0].size == 1 %>
 
-       <span class="empty_widget"><%= message('widget.timeline.timeline_not_displayed') -%></span>
+  <span class="empty_widget"><%= message('widget.timeline.timeline_not_displayed') -%></span>
 
 <% else %>
 
-       <div id="timeline-chart-<%= widget.id -%>"></div>
-       <script type="text/javascript+protovis">
-         function d(y,m,d,h,min,s) {
-           return new Date(y,m,d,h,min,s);
-         }
-         var data = <%= js_data -%>;
-         var snapshots = <%= js_snapshots -%>;
-         var metrics = <%= js_metrics -%>;
-         var events = <%= js_events ? js_events : "null" -%>;
-         var timeline = new SonarWidgets.Timeline('timeline-chart-<%= widget.id -%>')
-                                                       .height(<%= chartHeight -%>)
-                                                       .data(data)
-                                                       .snapshots(snapshots)
-                                                       .metrics(metrics)
-                                                       .events(events);
-         timeline.render();
-       
-       </script>
+  <div id="timeline-chart-<%= widget.id -%>"></div>
+  <script type="text/javascript+protovis">
+    function d(y, m, d, h, min, s) {
+      return new Date(y, m, d, h, min, s);
+    }
+    var data = <%= js_data -%>;
+    var snapshots = <%= js_snapshots -%>;
+    var metrics = <%= js_metrics -%>;
+    var events = <%= js_events ? js_events : "null" -%>;
+    var timeline = new SonarWidgets.Timeline('timeline-chart-<%= widget.id -%>')
+      .height(<%= chartHeight -%>)
+      .data(data)
+      .snapshots(snapshots)
+      .metrics(metrics)
+      .events(events);
+    timeline.render();
+
+  </script>
 
 <% end %>
\ No newline at end of file
index 81e9315bedb3ce7d75846aed3ce42b7837a1f8dc..1b69803b7c855acced8db6a23265706fdf3cea65 100644 (file)
@@ -42,7 +42,7 @@ public class SchemaMigration {
       - complete the Derby DDL file used for unit tests : sonar-testing-harness/src/main/resources/org/sonar/test/persistence/sonar-test.ddl
 
    */
-  public static final int LAST_VERSION = 236;
+  public static final int LAST_VERSION = 237;
 
   public final static String TABLE_NAME = "schema_migrations";
 
index d71e64228e4f38a387cf0f43af76765347a5bfe1..01a853910229fbc20faef8f2566801cf1ebffbc4 100644 (file)
@@ -25,7 +25,6 @@ public class WidgetPropertyDto {
   private Long widgetId;
   private String key;
   private String value;
-  private String valueType;
 
   /**
    * @return the id
@@ -35,8 +34,7 @@ public class WidgetPropertyDto {
   }
 
   /**
-   * @param id
-   *          the id to set
+   * @param id the id to set
    */
   public void setId(Long id) {
     this.id = id;
@@ -50,8 +48,7 @@ public class WidgetPropertyDto {
   }
 
   /**
-   * @param widgetId
-   *          the widgetId to set
+   * @param widgetId the widgetId to set
    */
   public void setWidgetId(Long widgetId) {
     this.widgetId = widgetId;
@@ -65,8 +62,7 @@ public class WidgetPropertyDto {
   }
 
   /**
-   * @param key
-   *          the key to set
+   * @param key the key to set
    */
   public void setKey(String key) {
     this.key = key;
@@ -80,26 +76,10 @@ public class WidgetPropertyDto {
   }
 
   /**
-   * @param value
-   *          the value to set
+   * @param value the value to set
    */
   public void setValue(String value) {
     this.value = value;
   }
 
-  /**
-   * @return the valueType
-   */
-  public String getValueType() {
-    return valueType;
-  }
-
-  /**
-   * @param valueType
-   *          the valueType to set
-   */
-  public void setValueType(String valueType) {
-    this.valueType = valueType;
-  }
-
 }
index 35234fd036f12f17b38162128aaa088b94b50f60..e3cf5c803f463f9aa068d63f73d2a744791701ad 100644 (file)
@@ -3,9 +3,9 @@
 
 <mapper namespace="org.sonar.persistence.dashboard.WidgetPropertyMapper">
 
-  <insert id="insert" parameterType="WidgetProperty" keyColumn="id" useGeneratedKeys="false" keyProperty ="id">
-    INSERT INTO widget_properties (id, widget_id, kee, text_value, value_type)
-    VALUES (widget_properties_seq.NEXTVAL, #{widgetId}, #{key, jdbcType=VARCHAR}, #{value, jdbcType=VARCHAR}, #{valueType, jdbcType=VARCHAR})
+  <insert id="insert" parameterType="WidgetProperty" keyColumn="id" useGeneratedKeys="false" keyProperty="id">
+    INSERT INTO widget_properties (id, widget_id, kee, text_value)
+    VALUES (widget_properties_seq.NEXTVAL, #{widgetId}, #{key, jdbcType=VARCHAR}, #{value, jdbcType=VARCHAR})
   </insert>
 
 </mapper>
index 9fafa59e58f3e3943b5a03e2159c84e68497de95..0ce1248fa27fbe32b99bbfc5b184336fa477e04e 100644 (file)
@@ -3,9 +3,9 @@
 
 <mapper namespace="org.sonar.persistence.dashboard.WidgetPropertyMapper">
 
-  <insert id="insert" parameterType="WidgetProperty" useGeneratedKeys="true" keyProperty ="id">
-    INSERT INTO widget_properties (widget_id, kee, text_value, value_type)
-    VALUES (#{widgetId}, #{key, jdbcType=VARCHAR}, #{value, jdbcType=VARCHAR}, #{valueType, jdbcType=VARCHAR})
+  <insert id="insert" parameterType="WidgetProperty" useGeneratedKeys="true" keyProperty="id">
+    INSERT INTO widget_properties (widget_id, kee, text_value)
+    VALUES (#{widgetId}, #{key, jdbcType=VARCHAR}, #{value, jdbcType=VARCHAR})
   </insert>
 
 </mapper>
index 294d38fd1556c32eab357173461e5ab410d097ee..fa0381c613cbc10ba3d698c8ad2ebe9ed170a28c 100644 (file)
@@ -165,6 +165,7 @@ INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('233');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('234');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('235');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('236');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('237');
 
 INSERT INTO USERS(ID, LOGIN, NAME, EMAIL, CRYPTED_PASSWORD, SALT, CREATED_AT, UPDATED_AT, REMEMBER_TOKEN, REMEMBER_TOKEN_EXPIRES_AT) VALUES (1, 'admin', 'Administrator', '', 'a373a0e667abb2604c1fd571eb4ad47fe8cc0878', '48bc4b0d93179b5103fd3885ea9119498e9d161b', '2011-09-26 22:27:48.0', '2011-09-26 22:27:48.0', null, null);
 ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 2;
index 66fa1a2704064bf648ebdc37b34b21c5fb7e861e..010332f89b6a2cb78503f1f17004d6df34cf5001 100644 (file)
@@ -183,8 +183,7 @@ CREATE TABLE "WIDGET_PROPERTIES" (
   "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
   "WIDGET_ID" INTEGER NOT NULL,
   "KEE" VARCHAR(100),
-  "TEXT_VALUE" VARCHAR(4000),
-  "VALUE_TYPE" VARCHAR(20)
+  "TEXT_VALUE" VARCHAR(4000)
 );
 
 CREATE TABLE "EVENTS" (
index 9b8c882e10075d321c980910adbcb2e54e1348bb..e7160dd02945a102f71d487e379f98f4d49f9c00 100644 (file)
  */
 package org.sonar.persistence.dashboard;
 
-import java.util.Date;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.sonar.persistence.DaoTestCase;
-import org.sonar.persistence.dashboard.DashboardDao;
-import org.sonar.persistence.dashboard.DashboardDto;
-import org.sonar.persistence.dashboard.WidgetDto;
-import org.sonar.persistence.dashboard.WidgetPropertyDto;
+
+import java.util.Date;
 
 public class DashboardDaoTest extends DaoTestCase {
 
@@ -67,12 +63,11 @@ public class DashboardDaoTest extends DaoTestCase {
     WidgetPropertyDto property = new WidgetPropertyDto();
     property.setKey("displayITs");
     property.setValue("true");
-    property.setValueType("BOOLEAN");
     widgetDto.addWidgetProperty(property);
 
     dao.insert(dashboardDto);
 
-    checkTables("shouldInsert", new String[] { "created_at", "updated_at" }, "dashboards", "widgets", "widget_properties");
+    checkTables("shouldInsert", new String[]{"created_at", "updated_at"}, "dashboards", "widgets", "widget_properties");
   }
 
   @Test
@@ -103,7 +98,6 @@ public class DashboardDaoTest extends DaoTestCase {
     WidgetPropertyDto property = new WidgetPropertyDto();
     property.setKey(null);
     property.setValue(null);
-    property.setValueType(null);
     widgetDto.addWidgetProperty(property);
 
     dao.insert(dashboardDto);
index 9515145dcceae08fb9f033cb9884ebc5c2eb6a70..91f73beae633f9ddcf72ee4c5feb5ab64da0a98e 100644 (file)
@@ -1,29 +1,28 @@
 <dataset>
 
   <dashboards
-      id="1"
-      kee="d-key"
-      user_id="6"
-      name="My Dashboard"
-      description="This is a dashboard"
-      column_layout="100%"
-      shared="1"/>
+    id="1"
+    kee="d-key"
+    user_id="6"
+    name="My Dashboard"
+    description="This is a dashboard"
+    column_layout="100%"
+    shared="[true]"/>
 
   <widgets
-      id="1"
-      dashboard_id="1"
-      widget_key="code_coverage"
-      name="Code coverage"
-      description="Widget for code coverage"
-      column_index="13"
-      row_index="14"
-      configured="1"/>
+    id="1"
+    dashboard_id="1"
+    widget_key="code_coverage"
+    name="Code coverage"
+    description="Widget for code coverage"
+    column_index="13"
+    row_index="14"
+    configured="[true]"/>
 
   <widget_properties
-      id="1"
-      widget_id="1"
-      kee="displayITs"
-      text_value="true"
-      value_type="BOOLEAN"/>  
+    id="1"
+    widget_id="1"
+    kee="displayITs"
+    text_value="true"/>
 
 </dataset>
index 729b5deef895c272862cdbbb3a6467788891ae96..787d1cb0d5e1cbc7130f403e2f08dee19f951b4c 100644 (file)
@@ -1,33 +1,32 @@
 <dataset>
 
   <dashboards
-      id="1"
-      kee="d-key"
-      user_id="[null]"
-      name="[null]"
-      description="[null]"
-      column_layout="[null]"
-      shared="1"
-      created_at="[null]"
-      updated_at="[null]"/>
+    id="1"
+    kee="d-key"
+    user_id="[null]"
+    name="[null]"
+    description="[null]"
+    column_layout="[null]"
+    shared="[true]"
+    created_at="[null]"
+    updated_at="[null]"/>
 
   <widgets
-      id="1"
-      dashboard_id="1"
-      widget_key="code_coverage"
-      name="[null]"
-      description="[null]"
-      column_index="[null]"
-      row_index="[null]"
-      configured="1"
-      created_at="[null]"
-      updated_at="[null]"/>
+    id="1"
+    dashboard_id="1"
+    widget_key="code_coverage"
+    name="[null]"
+    description="[null]"
+    column_index="[null]"
+    row_index="[null]"
+    configured="[true]"
+    created_at="[null]"
+    updated_at="[null]"/>
 
   <widget_properties
-      id="1"
-      widget_id="1"
-      kee="[null]"
-      text_value="[null]"
-      value_type="[null]"/>  
+    id="1"
+    widget_id="1"
+    kee="[null]"
+    text_value="[null]"/>
 
 </dataset>
index badeb5f78ec4b73ecc5359b2e46a7f7997537205..bad9fd1bb0e9ad410b4f441ce40cedde680a457a 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.server.ui;
 
+import com.google.common.collect.Maps;
 import org.apache.commons.lang.ArrayUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang.builder.CompareToBuilder;
@@ -27,6 +28,9 @@ import org.apache.commons.lang.builder.ToStringBuilder;
 import org.sonar.api.utils.AnnotationUtils;
 import org.sonar.api.web.*;
 
+import java.util.Collection;
+import java.util.Map;
+
 public class ViewProxy<V extends View> implements Comparable<ViewProxy> {
 
   private V view;
@@ -37,7 +41,7 @@ public class ViewProxy<V extends View> implements Comparable<ViewProxy> {
   private String[] resourceLanguages = {};
   private String[] defaultForMetrics = {};
   private String description = "";
-  private WidgetProperty[] widgetProperties = {};
+  private Map<String, WidgetProperty> widgetPropertiesByKey = Maps.newHashMap();
   private String[] widgetCategories = {};
   private WidgetLayoutType widgetLayout = WidgetLayoutType.DEFAULT;
   private boolean isDefaultTab = false;
@@ -90,7 +94,9 @@ public class ViewProxy<V extends View> implements Comparable<ViewProxy> {
 
     WidgetProperties propAnnotation = AnnotationUtils.getClassAnnotation(view, WidgetProperties.class);
     if (propAnnotation != null) {
-      this.widgetProperties = propAnnotation.value();
+      for (WidgetProperty property : propAnnotation.value()) {
+        widgetPropertiesByKey.put(property.key(), property);
+      }
     }
 
     WidgetCategory categAnnotation = AnnotationUtils.getClassAnnotation(view, WidgetCategory.class);
@@ -122,8 +128,12 @@ public class ViewProxy<V extends View> implements Comparable<ViewProxy> {
     return description;
   }
 
-  public WidgetProperty[] getWidgetProperties() {
-    return widgetProperties;
+  public Collection<WidgetProperty> getWidgetProperties() {
+    return widgetPropertiesByKey.values();
+  }
+
+  public WidgetProperty getWidgetProperty(String propertyKey) {
+    return widgetPropertiesByKey.get(propertyKey);
   }
 
   public String[] getWidgetCategories() {
@@ -175,12 +185,12 @@ public class ViewProxy<V extends View> implements Comparable<ViewProxy> {
   }
 
   public boolean isEditable() {
-    return !ArrayUtils.isEmpty(widgetProperties);
+    return !widgetPropertiesByKey.isEmpty();
   }
 
   public boolean hasRequiredProperties() {
     boolean requires = false;
-    for (WidgetProperty property : widgetProperties) {
+    for (WidgetProperty property : getWidgetProperties()) {
       if (!property.optional() && StringUtils.isEmpty(property.defaultValue())) {
         requires = true;
       }
@@ -207,29 +217,29 @@ public class ViewProxy<V extends View> implements Comparable<ViewProxy> {
     }
     ViewProxy rhs = (ViewProxy) obj;
     return new EqualsBuilder()
-        .append(getId(), rhs.getId())
-        .isEquals();
+      .append(getId(), rhs.getId())
+      .isEquals();
   }
 
   @Override
   public String toString() {
     return new ToStringBuilder(this)
-        .append("id", view.getId())
-        .append("sections", sections)
-        .append("userRoles", userRoles)
-        .append("scopes", resourceScopes)
-        .append("qualifiers", resourceQualifiers)
-        .append("languages", resourceLanguages)
-        .append("metrics", defaultForMetrics)
-        .toString();
+      .append("id", view.getId())
+      .append("sections", sections)
+      .append("userRoles", userRoles)
+      .append("scopes", resourceScopes)
+      .append("qualifiers", resourceQualifiers)
+      .append("languages", resourceLanguages)
+      .append("metrics", defaultForMetrics)
+      .toString();
 
   }
 
   public int compareTo(ViewProxy other) {
     return new CompareToBuilder()
-        .append(getTitle(), other.getTitle())
-        .append(getId(), other.getId())
-        .toComparison();
+      .append(getTitle(), other.getTitle())
+      .append(getId(), other.getId())
+      .toComparison();
 
   }
 }
\ No newline at end of file
index 1a05eac678a7b565ac2cdbda83e6f88e40f4a6f8..5f56517a2b7184c0ec312378b040d85b41b2ef30 100644 (file)
@@ -115,34 +115,20 @@ class DashboardController < ApplicationController
   def save_widget
     widget=Widget.find(params[:wid].to_i)
     #TODO check owner of dashboard
-    definition=java_facade.getWidget(widget.widget_key)
-    errors_by_property_key={}
-    definition.getWidgetProperties().each do |property_def|
-      value=params[property_def.key()] || property_def.defaultValue()
-      value='false' if value.empty? && property_def.type.name()==WidgetProperty::TYPE_BOOLEAN
-
-      errors=WidgetProperty.validate_definition(property_def, value)
-      if errors.empty?
-        widget.set_property(property_def.key(), value, property_def.type.name())
-      else
-        widget.unset_property(property_def.key())
-        errors_by_property_key[property_def.key()]=errors
+    Widget.transaction do
+      widget.properties.clear
+      widget.java_definition.getWidgetProperties().each do |java_property|
+        value=params[java_property.key()] || java_property.defaultValue()
+        if value && !value.empty?
+          prop = widget.properties.build(:kee => java_property.key, :text_value => value)
+          prop.save!
+        end
       end
-    end
-
-    if errors_by_property_key.empty?
       widget.configured=true
-      widget.save
-      widget.properties.each { |p| p.save }
+      widget.save!
       render :update do |page|
         page.redirect_to(url_for(:action => :configure, :did => widget.dashboard_id, :id => params[:id]))
       end
-    else
-      widget.configured=false
-      widget.save
-      render :update do |page|
-        page.replace_html "widget_props_#{widget.id}", :partial => 'dashboard/widget_properties', :locals => {:widget => widget, :definition => definition, :errors_by_property_key => errors_by_property_key}
-      end
     end
   end
 
index 7a10a4791ecf8fc4abf49b51bb713354ba1706c3..24e8616d3de9a0ab56e6574c4da79fa7344bae19 100644 (file)
@@ -21,14 +21,14 @@ class Widget < ActiveRecord::Base
   has_many :properties, :dependent => :delete_all, :class_name => 'WidgetProperty'
   belongs_to :dashboards
 
-  validates_presence_of     :name
-  validates_length_of       :name,    :within => 1..256
+  validates_presence_of :name
+  validates_length_of :name, :within => 1..256
 
-  validates_presence_of     :widget_key
-  validates_length_of       :widget_key, :within => 1..256
+  validates_presence_of :widget_key
+  validates_length_of :widget_key, :within => 1..256
 
   def property(key)
-    properties().each do |p|
+    self.properties().each do |p|
       return p if (p.key==key)
     end
     nil
@@ -42,43 +42,33 @@ class Widget < ActiveRecord::Base
     "block_#{id}"
   end
 
-  def property_value(key, default_value=nil)
+  def property_text_value(key)
     prop=property(key)
-    (prop ? prop.value : nil) || default_value
+    prop ? prop.text_value : nil
   end
 
-  def set_property(key, value, value_type)
+  def property_value(key)
     prop=property(key)
-    if prop
-      prop.text_value=value
-      prop.value_type=value_type
-    else
-      prop=self.properties.build(:kee => key, :text_value => value, :value_type => value_type)
-    end
-    properties_as_hash[key]=prop.typed_value
-  end
-
-  def unset_property(key)
-    prop=property(key)
-    self.properties.delete(prop) if prop
-  end
-
-  def delete_property(key)
-    prop=property(key)
-    if prop
-      properties.delete(prop)
-    end
+    prop ? prop.value : nil
   end
 
   def properties_as_hash
     @properties_hash ||=
       begin
         hash={}
-        properties.each do |prop|
-          hash[prop.key]=prop.typed_value
+        java_definition.getWidgetProperties().each do |property_definition|
+          prop = property(property_definition.key)
+          hash[property_definition.key]=(prop ? prop.value : WidgetProperty.text_to_value(property_definition.defaultValue(), property_definition.type().name()))
         end
         hash
       end
-    @properties_hash
+  end
+
+  def java_definition
+    Java::OrgSonarServerUi::JRubyFacade.getInstance().getWidget(key)
+  end
+
+  def layout
+    java_definition.getWidgetLayout().name()
   end
 end
\ No newline at end of file
index 4aa241e38d3adab63c3a93665fe823f32366ed3e..6697aedcaa88c0ba264c31c82452a3bf829ddef8 100644 (file)
@@ -26,59 +26,77 @@ class WidgetProperty < ActiveRecord::Base
 
   belongs_to :widget
 
-  validates_length_of       :kee, :within => 1..100
-  validates_length_of       :text_value,   :maximum => 4000, :allow_blank => true, :allow_nil => true
+  validates_length_of :kee, :within => 1..100
+  validates_length_of :text_value, :maximum => 4000, :allow_blank => true, :allow_nil => true
 
   def key
     kee
   end
 
-  def value
-    text_value
+  def text_value
+    read_attribute(:text_value) || default_text_value
   end
 
-  def typed_value
-    case value_type
-    when TYPE_INTEGER
-      value.to_i
-    when TYPE_FLOAT
-      Float(value)
-    when TYPE_BOOLEAN
-      value=='true'
-    when TYPE_METRIC
-      Metric.by_key(value.to_s)
-    else
-      value
-    end
+  def default_text_value
+    java_definition.defaultValue()
+  end
+
+  def type
+    @type ||=
+      begin
+        java_definition.type().name()
+      end
+  end
+
+  def java_definition
+    @java_definition ||=
+      begin
+        widget.java_definition.getWidgetProperty(key)
+      end
+  end
+
+  def value
+    WidgetProperty.text_to_value(text_value, type)
   end
 
   def to_hash_json
-    {:key => key, :value => value.to_s}
+    {:key => key, :value => text_value}
   end
 
   def to_xml(xml=Builder::XmlMarkup.new(:indent => 0))
     xml.property do
       xml.key(prop_key)
-      xml.value {xml.cdata!(text_value.to_s)}
+      xml.value { xml.cdata!(text_value) }
     end
     xml
   end
 
-  def self.validate_definition(definition, value)
-    errors=[]
-    if value.empty?
-      errors<<"Missing value" unless definition.optional()
+  def self.text_to_value(text, type)
+    case type
+      when TYPE_INTEGER
+        text.to_i
+      when TYPE_FLOAT
+        Float(text)
+      when TYPE_BOOLEAN
+        text=='true'
+      when TYPE_METRIC
+        Metric.by_key(text)
+      else
+        text
+    end
+  end
+
+  protected
+  def validate
+    errors.add_to_base("Unknown property: #{key}") unless java_definition
+    errors.add_to_base("Unknown type for property #{key}") unless type
+    if text_value.empty?
+      errors.add_to_base("#{key} is empty") unless java_definition.optional()
     else
-      errors<<"Please type an integer (example: 123)" if definition.type.name()==TYPE_INTEGER && value.to_i.to_s!=value
-      if definition.type.name()==TYPE_FLOAT
-        begin
-          Float(value)
-        rescue
-          errors<<"Please type a number (example: 123.45)"
-        end
-      end
-      errors<<"Please check value" if definition.type.name()==TYPE_BOOLEAN && !(value=="true" || value=="false")
+      errors.add_to_base("#{key} is not an integer") if type==TYPE_INTEGER && !Api::Utils.is_integer?(text_value)
+      errors.add_to_base("#{key} is not a decimal number") if type==TYPE_FLOAT && !Api::Utils.is_number?(text_value)
+      errors.add_to_base("#{key} is not a boolean") if type==TYPE_BOOLEAN && !(text_value=="true" || text_value=="false")
     end
-    errors
   end
+
 end
\ No newline at end of file
index 92d817dae956fe7fe76a3ebf4b56dcf6280ca555..c27485fcf58e5a334815808dfa02040dbcb17efe 100644 (file)
@@ -1,48 +1,50 @@
- <%
+<%
    begin
-     widget_body=render :inline => definition.getTarget().getTemplate(), :locals => {:widget_properties => widget.properties_as_hash, :widget => widget, :dashboard_configuration => @dashboard_configuration}
+     widget_body=render :inline => widget.java_definition.getTarget().getTemplate(), :locals => {:widget_properties => widget.properties_as_hash, :widget => widget, :dashboard_configuration => @dashboard_configuration}
    rescue => error
-      logger.error(message('dashboard.cannot_render_widget_x', :params => [definition.getId(), error]))
-      logger.error(error.backtrace.join("\n"))
-      widget_body=""
+     logger.error(message('dashboard.cannot_render_widget_x', :params => [widget.java_definition.getId(), error]))
+     logger.error(error.backtrace.join("\n"))
+     widget_body=""
    end
- %>
+%>
 
- <div class="handle" style="//overflow:hidden;//zoom:1;">
-   <a class="block-remove"  onclick="portal.deleteWidget(this);return false;"><%= message('delete') -%></a>
-   <% if definition.isEditable() %>
-     <a class="block-view-toggle" onclick="portal.editWidget(<%= widget.id -%>);return false;"><%= message('edit') -%></a>
-   <% end %>
-   <%= h message('widget.' + definition.getId() + '.name', :default => definition.getTitle()) -%>
- </div>
+<div class="handle" style="//overflow:hidden;//zoom:1;">
+  <a class="block-remove" onclick="portal.deleteWidget(this);return false;"><%= message('delete') -%></a>
+  <% if widget.java_definition.isEditable() %>
+    <a class="block-view-toggle" onclick="portal.editWidget(<%= widget.id -%>);return false;"><%= message('edit') -%></a>
+  <% end %>
+  <%= h message('widget.' + widget.java_definition.getId() + '.name', :default => widget.java_definition.getTitle()) -%>
+</div>
 
 
- <div class="widget_props" id="widget_props_<%= widget.id -%>" style="<%= 'display:none' if widget.configured -%>">
-   <%= render :partial => 'dashboard/widget_properties', :locals => {:widget => widget, :definition => definition} -%>
- </div>
+<div class="widget_props" id="widget_props_<%= widget.id -%>" style="<%= 'display:none' if widget.configured -%>">
+  <%= render :partial => 'dashboard/widget_properties', :locals => {:widget => widget} -%>
+</div>
 
 
- <div id="widget_<%= widget.id -%>" class="configure_widget <%= definition.getId() -%>" style="height:100%;<%= 'display:none;' if !widget.configured -%>">
-   <!--[if lte IE 6]>
-   <style type="text/css">
-     #dashboard .block .content .transparent {
-         display: none;
-     }
-   </style>
-   <![endif]-->
- <div class="transparent"></div>
-   <% if widget_body.include? '<' %>
-     <%
-       default_layout=(definition.getWidgetLayout().name()=='DEFAULT')
+<div id="widget_<%= widget.id -%>" class="configure_widget <%= widget.java_definition.getId() -%>" style="height:100%;<%= 'display:none;' if !widget.configured -%>">
+  <!--[if lte IE 6]>
+  <style type="text/css">
+    #dashboard .block .content .transparent {
+      display: none;
+    }
+  </style>
+  <![endif]-->
 <div class="transparent"></div>
+  <% if widget_body.include? '<' %>
+    <%
+       default_layout=(widget.layout=='DEFAULT')
        if default_layout
-     %>
-       <div class="widget">
-     <% end %>
-     <%= widget_body -%>
-     <% if default_layout %><div class="clear"> </div></div><% end %>
-   <% else %>
-   <div class="widget"><p><%= message('no_data') -%></p></div>
-   <% end %>
- <div style="clear: both;"></div>
- </div>
+    %>
+      <div class="widget">
+    <% end %>
+    <%= widget_body -%>
+    <% if default_layout %>
+      <div class="clear"> </div></div>
+    <% end %>
+  <% else %>
+    <div class="widget"><p><%= message('no_data') -%></p></div>
+  <% end %>
+  <div style="clear: both;"></div>
+</div>
 
index 54265983a6fda647ddca9f88128a292b4c7cad84..49a370f57b12a6d71274e304552cca3e438e7f89 100644 (file)
@@ -1,31 +1,35 @@
-<div class="<%= definition.getId() %>" style="height:100%;">
-<% if widget.configured %>
-  <%
-    begin
-      widget_body=render :inline => definition.getTarget().getTemplate(), :locals => {:widget_properties => widget.properties_as_hash, :widget => widget, :dashboard_configuration => @dashboard_configuration}
-    rescue => error
-       logger.error(message('dashboard.cannot_render_widget_x', :params => [definition.getId(), error]))
-       logger.error(error.backtrace.join("\n"))
-       widget_body=""
-    end
+<div class="<%= widget.key %>" style="height:100%;">
+  <% if widget.configured %>
+    <%
+       begin
+         widget_body=render :inline => widget.java_definition.getTarget().getTemplate(), :locals => {:widget_properties => widget.properties_as_hash, :widget => widget, :dashboard_configuration => @dashboard_configuration}
+       rescue => error
+         logger.error(message('dashboard.cannot_render_widget_x', :params => [widget.key, error]))
+         logger.error(error.backtrace.join("\n"))
+         widget_body=""
+       end
 
-    if widget_body.include?('<')
-  %>
+       if widget_body.include?('<')
+    %>
+      <%
+         default_layout=(widget.java_definition.getWidgetLayout().name()=='DEFAULT')
+         if default_layout
+      %>
+        <div class="widget">
+      <% end %>
+      <%= widget_body -%>
+      <% if default_layout %>
+        <div class="clear"> </div></div>
+      <% end %>
     <%
-      default_layout=(definition.getWidgetLayout().name()=='DEFAULT')
-      if default_layout
+       end
     %>
-      <div class="widget">
-    <% end %>
-    <%= widget_body -%>
-    <% if default_layout %><div class="clear"> </div></div><% end %>
-  <%
-    end
-  %>
-<% else %>
-  <div class="widget">
-  <p><a href="<%= url_for :action => :configure, :did => @dashboard.id, :id => @resource.id -%>"><%= message('dashboard.please_configure_the_widget_x', :params => definition.getTitle()) -%></a></p>
-  </div>
-<% end %>
-<div style="clear: both;"></div>
+  <% else %>
+    <div class="widget">
+      <p>
+        <a href="<%= url_for :action => :configure, :did => @dashboard.id, :id => @resource.id -%>"><%= message('dashboard.please_configure_the_widget_x', :params => widget.java_definition.getTitle()) -%></a>
+      </p>
+    </div>
+  <% end %>
+  <div style="clear: both;"></div>
 </div>
\ No newline at end of file
index 6126d0999dbb3d054ba41d2b339e2330884c20f1..aa7a65bfd48282282d38178dea99af287a0342ae 100644 (file)
@@ -1,9 +1,10 @@
 <td>
-<div class="widget_def" id="def_<%= definition.getId().tr('_', '') -%>">
-<p><b><%= h message('widget.' + definition.getId() + '.name', :default => definition.getTitle()) -%></b></p>
-<p><%= h message('widget.' + definition.getId() + '.description', :default => definition.getDescription()) -%></p>
-<%= form_tag :action => 'add_widget', :did => dashboard_id, :id => resource_id, :widget => definition.getId() %>
-<input type="submit" value="<%= message('dashboard.add_widget') -%>" >
-</form>
-</div>
+  <div class="widget_def" id="def_<%= definition.getId().tr('_', '') -%>">
+    <p><b><%= h message('widget.' + definition.getId() + '.name', :default => definition.getTitle()) -%></b></p>
+
+    <p><%= h message('widget.' + definition.getId() + '.description', :default => definition.getDescription()) -%></p>
+    <%= form_tag :action => 'add_widget', :did => dashboard_id, :id => resource_id, :widget => definition.getId() %>
+    <input type="submit" value="<%= message('dashboard.add_widget') -%>">
+    </form>
+  </div>
 </td>
index 949fda10184f42d4f8af58a569b5ffe602198b6a..e071c6ce7e1c44dd16e819c4e81227339393f9cb 100644 (file)
@@ -1,35 +1,30 @@
-<% form_remote_tag :url => {:action => 'save_widget', :wid => widget.id, :id => params[:id]}, :method => :post do -%>
-  <% if defined?(errors_by_property_key) && errors_by_property_key %>
-    <ul>
-       <% errors_by_property_key.each_pair do |property_key, error| %>
-         <li class="error"><%= property_key -%>: <%= h(error)-%></li>
-       </ul>
-       <% end %>
-  <% end %>
-    <table class="form width100">
-         <tbody>
-      <% definition.getWidgetProperties().each do |property_def|
-          value=widget.property_value(property_def.key(), property_def.defaultValue())
-      %>
-          <tr>
-            <td valign="top" class="thin nowrap"><b><%= property_def.key() -%></b><%= "*" unless property_def.optional()==true -%>: </td>
-            <td id="row_<%= property_def.key() -%>">
-              <%= property_value_field(property_def, value) -%>
-              <span class="note">
+<% form_remote_tag :url => {:action => 'save_widget', :wid => widget.id, :id => params[:id]},
+                   :method => :post,
+                   :update => {:failure => "error#{widget.id}"},
+                   :failure => "$('error#{widget.id}').show()" do -%>
+  <div id="error<%= widget.id -%>" class="error" style="display: none"></div>
+  <table class="form width100">
+    <tbody>
+    <% widget.java_definition.getWidgetProperties().each do |property_def| %>
+      <tr>
+        <td valign="top" class="thin nowrap"><b><%= property_def.key() -%></b><%= "*" unless property_def.optional()==true -%>:</td>
+        <td id="row_<%= property_def.key() -%>">
+          <%= property_value_field(property_def, widget.property_text_value(property_def.key())) -%>
+          <span class="note">
                 <%= message("widget." + widget.key + ".param." + property_def.key(), :default => property_def.description()) -%>
               </span>
-            </td>
-          </tr>
-      <% end %>
-      <tr>
-        <td colspan="2">
-          <%= submit_tag message('save') %>
-          <% if widget.configured %>
-            <a href="#" onClick="portal.cancelEditWidget(<%= widget.id -%>);return false;"><%= message('cancel') -%></a>
-          <% end %>
         </td>
       </tr>
-      </tbody>
-    </table>
-    <%= hidden_field_tag "widgetid", "", :class => "widgetid" %>
+    <% end %>
+    <tr>
+      <td colspan="2">
+        <%= submit_tag message('save') %>
+        <% if widget.configured %>
+          <a href="#" onClick="portal.cancelEditWidget(<%= widget.id -%>);return false;"><%= message('cancel') -%></a>
+        <% end %>
+      </td>
+    </tr>
+    </tbody>
+  </table>
+  <%= hidden_field_tag "widgetid", "", :class => "widgetid" %>
 <% end -%>
\ No newline at end of file
index 75c89a89aa0f919c43615afc56be457b5c9e3602..54b9856d40d7d8214b0905797cf87f93d9598857 100644 (file)
@@ -1,70 +1,67 @@
 <script type="text/javascript">
-    <!--
-    var options = {
-        editorEnabled: true,
-        portal: 'dashboard',
-        column: 'dashboard-column',
-        columnhandle: 'column-handle',
-        block: 'block',
-        handle: 'none',
-        hoverclass: 'block-hover',
-        dashboardstate: 'dashboardstate',
-        toggle: 'block-toggle',
-        blocklist: 'widget_defs',
-        highlight_duration: 2,
-        highlight_startcolor: '#cae3f2',
-        highlight_endcolor: '#ffffff',
-        saveurl: '<%= url_for :action => 'set_dashboard', :did => @dashboard.id, :id => @resource.id -%>'
-    };
-    var portal;
-    function init_dashboard() {
-      portal = new Portal(options);
-      <% if params[:highlight] %>
-      portal.highlightWidget(<%= params[:highlight] -%>);
-      <% end %>
-    }
-    Event.observe(window, 'load', init_dashboard, false);
+  <!--
+  var options = {
+    editorEnabled:true,
+    portal:'dashboard',
+    column:'dashboard-column',
+    columnhandle:'column-handle',
+    block:'block',
+    handle:'none',
+    hoverclass:'block-hover',
+    dashboardstate:'dashboardstate',
+    toggle:'block-toggle',
+    blocklist:'widget_defs',
+    highlight_duration:2,
+    highlight_startcolor:'#cae3f2',
+    highlight_endcolor:'#ffffff',
+    saveurl:'<%= url_for :action => 'set_dashboard', :did => @dashboard.id, :id => @resource.id -%>'
+  };
+  var portal;
+  function init_dashboard() {
+    portal = new Portal(options);
+  <% if params[:highlight] %>
+    portal.highlightWidget(<%= params[:highlight] -%>);
+  <% end %>
+  }
+  Event.observe(window, 'load', init_dashboard, false);
+
+  function filterWidgets(category) {
+    new Ajax.Updater(
+      'widget_defs',
+      '<%= url_for :controller => "dashboard", :action => "widget_definitions", :did => @dashboard.id, :id => @resource.id -%>&category=' + category,
+      {asynchronous:true, evalScripts:true});
+    $('filter-widgets-loading').show();
+    return false;
+  }
 
-    function filterWidgets(category){
-      new Ajax.Updater(
-        'widget_defs',
-        '<%= url_for :controller => "dashboard", :action => "widget_definitions", :did => @dashboard.id, :id => @resource.id -%>&category=' + category,
-        {asynchronous:true, evalScripts:true});
-      $('filter-widgets-loading').show();
-      return false;
-    }
-    
-    //-->
+  //-->
 </script>
 
 <div id="dashboard">
   <%= render :partial => 'dashboard/header', :locals => {:back => true} %>
 
   <div id="widget_defs">
-    <%= render :partial => 'dashboard/widget_definitions', :locals => {:dashboard_id => @dashboard.id, :resource_id => @resource.id, :filter_on_category => nil}-%>
+    <%= render :partial => 'dashboard/widget_definitions', :locals => {:dashboard_id => @dashboard.id, :resource_id => @resource.id, :filter_on_category => nil} -%>
   </div>
 
 
   <%
-    columns=@dashboard.column_layout.split('-')
-    for index in 1..columns.size()
+     columns=@dashboard.column_layout.split('-')
+     for index in 1..columns.size()
   %>
     <div class="dashboard-column-wrapper" style="width: <%= columns[index-1] -%>">
-    <div class="dashboard-column" id="dashboard-column-<%= index -%>" style="margin: 0px <%= index<columns.size() ? "5px" : "0px" -%> 0px <%= index>1 ? "5px" : "0px" -%>;">
-      <div class="column-handle" style="display: none"> </div>
+      <div class="dashboard-column" id="dashboard-column-<%= index -%>" style="margin: 0 <%= index<columns.size() ? "5px" : "0px" -%> 0 <%= index>1 ? "5px" : "0px" -%>;">
+        <div class="column-handle" style="display: none"></div>
 
-    <%
-      @dashboard.widgets.select{|widget| widget.column_index==index}.sort_by{|widget| widget.row_index}.each do |widget|
-        widget_definition=@widget_definitions.find{|wd| wd.getId()==widget.widget_key }
-        if widget_definition
-    %>
-        <div class="block" id="block_<%= widget.id -%>">
-          <%= render :partial => 'dashboard/configure_widget', :locals => {:widget => widget,  :definition => widget_definition} %>
-        </div>
-    <%
-        end
-      end
-    %>
+        <%
+           @dashboard.widgets.select { |widget| widget.column_index==index }.sort_by { |widget| widget.row_index }.each do |widget|
+        %>
+          <div class="block" id="block_<%= widget.id -%>">
+            <%= render :partial => 'dashboard/configure_widget', :locals => {:widget => widget} %>
+          </div>
+        <%
+           end
+        %>
       </div>
     </div>
   <% end %>
diff --git a/sonar-server/src/main/webapp/WEB-INF/db/migrate/237_delete_value_type_from_widget_properties.rb b/sonar-server/src/main/webapp/WEB-INF/db/migrate/237_delete_value_type_from_widget_properties.rb
new file mode 100644 (file)
index 0000000..874312d
--- /dev/null
@@ -0,0 +1,31 @@
+#
+# Sonar, entreprise quality control tool.
+# Copyright (C) 2008-2011 SonarSource
+# mailto:contact AT sonarsource DOT com
+#
+# Sonar is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 3 of the License, or (at your option) any later version.
+#
+# Sonar is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with Sonar; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+#
+
+#
+# Sonar 2.13
+#
+class DeleteValueTypeFromWidgetProperties < ActiveRecord::Migration
+
+  def self.up
+    remove_column('widget_properties', 'value_type')
+    WidgetProperty.reset_column_information()
+  end
+
+end
index 06c4ea36332bb9210dc326cfd1d57d4559fb7ca9..5b8c69c248494485889251001252252288ebf0f2 100644 (file)
@@ -119,7 +119,7 @@ public class ViewProxyTest {
   public void widgetShouldBeEditable() {
     ViewProxy proxy = new ViewProxy<Widget>(new EditableWidget());
     assertThat(proxy.isEditable(), is(true));
-    assertThat(proxy.getWidgetProperties().length, is(2));
+    assertThat(proxy.getWidgetProperties().size(), is(2));
   }
 
   @Test
@@ -153,8 +153,8 @@ class FakeView implements View {
 }
 
 @WidgetProperties({
-    @WidgetProperty(key="foo", optional = false),
-    @WidgetProperty(key="bar", defaultValue = "30", type = WidgetPropertyType.INTEGER)
+  @WidgetProperty(key = "foo", optional = false),
+  @WidgetProperty(key = "bar", defaultValue = "30", type = WidgetPropertyType.INTEGER)
 })
 class EditableWidget implements Widget {
 
@@ -168,8 +168,8 @@ class EditableWidget implements Widget {
 }
 
 @WidgetProperties({
-    @WidgetProperty(key="foo"),
-    @WidgetProperty(key="bar")
+  @WidgetProperty(key = "foo"),
+  @WidgetProperty(key = "bar")
 })
 class WidgetWithOptionalProperties implements Widget {