*/
package org.sonar.plugins.core.widgets;
-import org.sonar.api.web.*;
+import org.sonar.api.web.AbstractRubyTemplate;
+import org.sonar.api.web.RubyRailsWidget;
+import org.sonar.api.web.WidgetProperties;
+import org.sonar.api.web.WidgetProperty;
+import org.sonar.api.web.WidgetPropertyType;
@WidgetProperties(
{
+ @WidgetProperty(key = "chartTitle", type = WidgetPropertyType.STRING),
@WidgetProperty(key = "metric1", type = WidgetPropertyType.METRIC),
@WidgetProperty(key = "metric2", type = WidgetPropertyType.METRIC),
@WidgetProperty(key = "metric3", type = WidgetPropertyType.METRIC),
@Override
protected String getTemplatePath() {
- return "/org/sonar/plugins/core/widgets/timeline.html.erb";
- //return "/Users/fbellingard/Documents/Sonar/repos/sonar/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/timeline.html.erb";
+ //return "/org/sonar/plugins/core/widgets/timeline.html.erb";
+ return "/Users/fbellingard/Documents/Sonar/repos/sonar/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/timeline.html.erb";
}
}
\ No newline at end of file
<%= javascript_include_tag 'protovis-sonar' %>
-
-<div id="timeline-chart"></div>
-
-<script type="text/javascript+protovis">
-
<%
metric_data_map = {}
(1..3).each do |index|
end
end
- trends = TrendsChart.time_machine_measures(@resource, metric_data_map.keys, {}).sort { |t1, t2| t1["created_at"] <=> t2["created_at"] }
- trends.each() do |trend_item|
+ options = {}
+ from_date = dashboard_configuration.from_datetime
+ if from_date
+ options[:from] = from_date
+ end
+
+ TrendsChart.time_machine_measures(@resource, metric_data_map.keys, options).each() do |trend_item|
metric_data_map[trend_item["metric_id"].to_i] << {:date => trend_item["created_at"], :value => trend_item["value"]}
end
js_data += "["
metric_data_map[metric_id].each() do |metric_data|
m_date = Time.parse(metric_data[:date])
- js_data += "{\"x\":new Date("
- js_data += m_date.strftime("%Y,%m,%d")
- js_data += "),\"y\":\""
- js_data += metric_data[:value]
- js_data += "\"},"
+ 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 += "),\"y\":"
+ js_data += sprintf( "%0.02f", metric_data[:value])
+ js_data += "},"
end
js_data += "],"
end
js_data += "]"
%>
- var data = <%= js_data -%>;
-
- displayTrendChart('timeline-chart', data);
+
+<% if widget_properties["chartTitle"] %>
+<h3 style="text-align: center; margin-bottom: 10px"><%= h(widget_properties["chartTitle"]) -%></h3>
+<% end %>
+
+
+<div id="timeline-chart-<%= widget.id -%>"></div>
+<script type="text/javascript+protovis">
+ function d(y,m,d) {
+ return new Date(y,m,d);
+ }
+ var data = <%= js_data -%>;
+ var timeline = new SonarWidgets.Timeline('timeline-chart-<%= widget.id -%>').data(data);
+ timeline.render();
</script>
\ No newline at end of file
<include>**/prototip-min.js</include>
<include>**/dashboard-min.js</include>
<include>**/protovis-min.js</include>
+ <include>**/protovis-sonar-min.js</include>
</includes>
<output>${project.build.directory}/${project.build.finalName}/javascripts/sonar.js</output>
</aggregation>
init_series(java_chart, metrics)
metric_ids=metrics.map{|m| m.id}
add_measures(java_chart, time_machine_measures(resource, metric_ids, options))
- add_measures(java_chart, time_machine_reviews(resource, metric_ids, options))
add_labels(java_chart, resource);
export_chart_as_png(java_chart)
if (options[:to])
sql += ' and s.created_at<=?'
end
+ sql += ' order by s.created_at ASC'
conditions=[sql, Snapshot::STATUS_PROCESSED, resource.id, metric_ids]
if (options[:from])
conditions<<options[:from]
<%= javascript_include_tag 'prototip' %>
<%= javascript_include_tag 'dashboard' %>
<%= javascript_include_tag 'protovis' %>
+<%= javascript_include_tag 'protovis-sonar' %>
<% end %>
<!--[if lte IE 6]>
<link href="<%= ApplicationController.root_context -%>/ie6/index" media="all" rel="stylesheet" type="text/css" />
-function displayTrendChart(divId, data) {
+window.SonarWidgets = {}
+SonarWidgets.Timeline = function (divId) {
+ this.wDivId = divId;
+ this.wData;
+ this.data = function(data) {
+ this.wData = data;
+ return this;
+ }
+}
+
+SonarWidgets.Timeline.prototype.render = function() {
+
+ var widgetDiv = document.getElementById(this.wDivId);
+
/* Sizing and scales. */
- var w = 400 - 40,
+ var w = widgetDiv.parentNode.clientWidth - 60,
h = 300 - 25,
S=2;
/* The root panel. */
var vis = new pv.Panel()
- .canvas(document.getElementById(divId))
- .width(w)
- .height(h)
- .left(30)
- .right(10)
- .bottom(20)
- .top(5)
- .strokeStyle("#CCC");
+ .canvas(widgetDiv)
+ .width(w)
+ .height(h)
+ .left(30)
+ .right(20)
+ .bottom(20)
+ .top(5)
+ .strokeStyle("#CCC");
/* X-axis */
vis.add(pv.Rule)
- .data(x.ticks())
- .left(x)
- .bottom(-5)
- .height(5)
- .anchor("bottom")
- .add(pv.Label)
- .text(x.tickFormat);
+ .data(x.ticks())
+ .left(x)
+ .bottom(-5)
+ .height(5)
+ .anchor("bottom")
+ .add(pv.Label)
+ .text(x.tickFormat);
/* Y-axis and ticks. */
var show_y_axis = (data.length==1)
/* A panel for each data series. */
var panel = vis.add(pv.Panel)
- .data(data);
+ .data(this.wData);
/* The line. */
var line = panel.add(pv.Line)
- .data(function(array) {return array;})
- .left(function(d) {return x(d.x);})
- .bottom(function(d) {return y[this.parent.index](d.y);})
- .interpolate(function() {return interpolate;})
- .lineWidth(2);
+ .data(function(array) {return array;})
+ .left(function(d) {return x(d.x);})
+ .bottom(function(d) {return y[this.parent.index](d.y);})
+ .interpolate(function() {return interpolate;})
+ .lineWidth(2);
/* The mouseover dots and label. */
line.add(pv.Dot)
- .visible(function() {return idx >= 0;})
- .data(function(d) {return [d[idx]];})
- .fillStyle(function() {return line.strokeStyle();})
- .strokeStyle("#000")
- .size(20)
- .lineWidth(1)
- .add(pv.Dot)
- .left(10)
- .bottom(function() {return this.parent.index * 12 + 10;})
- .anchor("right").add(pv.Label)
- .text(function(d) {return d.y.toFixed(2);});
+ .visible(function() {return idx >= 0;})
+ .data(function(d) {return [d[idx]];})
+ .fillStyle(function() {return line.strokeStyle();})
+ .strokeStyle("#000")
+ .size(20)
+ .lineWidth(1)
+ .add(pv.Dot)
+ .left(10)
+ .bottom(function() {return this.parent.index * 12 + 10;})
+ .anchor("right").add(pv.Label)
+ .text(function(d) {return d.y.toFixed(2);});
/* An invisible bar to capture events (without flickering). */
vis.add(pv.Bar)
- .fillStyle("rgba(0,0,0,.001)")
- .event("mouseout", function() {
- i = -1;
- return vis;
- })
- .event("mousemove", function() {
- var mx = x.invert(vis.mouse().x);
- idx = pv.search(data[0].map(function(d) {return d.x;}), mx);
- idx = idx < 0 ? (-idx - 2) : idx;
- return vis;
- });
+ .fillStyle("rgba(0,0,0,.001)")
+ .event("mouseout", function() {
+ i = -1;
+ return vis;
+ })
+ .event("mousemove", function() {
+ var mx = x.invert(vis.mouse().x);
+ idx = pv.search(data[0].map(function(d) {return d.x;}), mx);
+ idx = idx < 0 ? (-idx - 2) : idx;
+ return vis;
+ });
+
vis.render();
-};
\ No newline at end of file
+
+}
\ No newline at end of file