@@ -17,17 +17,22 @@ package com.gitblit.wicket.charting; | |||
import java.io.Serializable; | |||
import java.util.ArrayList; | |||
import java.util.Date; | |||
import java.util.List; | |||
import java.util.TimeZone; | |||
import com.gitblit.Keys; | |||
import com.gitblit.utils.StringUtils; | |||
import com.gitblit.wicket.GitBlitWebApp; | |||
import com.gitblit.wicket.GitBlitWebSession; | |||
/** | |||
* Abstract parent class for Google Charts built with the Visualization API. | |||
* Abstract parent class for different type of chart: bar, pie & line | |||
* | |||
* @author James Moger | |||
* | |||
*/ | |||
public abstract class GoogleChart implements Serializable { | |||
public abstract class Chart implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
final String tagId; | |||
@@ -36,17 +41,21 @@ public abstract class GoogleChart implements Serializable { | |||
final String keyName; | |||
final String valueName; | |||
final List<ChartValue> values; | |||
final List<ChartValue> highlights; | |||
int width; | |||
int height; | |||
boolean showLegend; | |||
String dateFormat = "MMM dd"; | |||
String clickUrl = null; | |||
public GoogleChart(String tagId, String title, String keyName, String valueName) { | |||
public Chart(String tagId, String title, String keyName, String valueName) { | |||
this.tagId = tagId; | |||
this.dataName = StringUtils.getSHA1(title).substring(0, 8); | |||
this.dataName = StringUtils.getSHA1(tagId).substring(0, 8); | |||
this.title = title; | |||
this.keyName = keyName; | |||
this.valueName = valueName; | |||
values = new ArrayList<ChartValue>(); | |||
highlights = new ArrayList<ChartValue>(); | |||
showLegend = true; | |||
} | |||
@@ -73,6 +82,14 @@ public abstract class GoogleChart implements Serializable { | |||
public void addValue(String name, double value) { | |||
values.add(new ChartValue(name, (float) value)); | |||
} | |||
public void addValue(Date date, int value) { | |||
values.add(new ChartValue(String.valueOf(date.getTime()), value)); | |||
} | |||
public void addHighlight(Date date, int value) { | |||
highlights.add(new ChartValue(String.valueOf(date.getTime()), value)); | |||
} | |||
protected abstract void appendChart(StringBuilder sb); | |||
@@ -80,6 +97,11 @@ public abstract class GoogleChart implements Serializable { | |||
sb.append(line); | |||
sb.append('\n'); | |||
} | |||
protected TimeZone getTimeZone() { | |||
return GitBlitWebApp.get().settings().getBoolean(Keys.web.useClientTimezone, false) ? GitBlitWebSession.get() | |||
.getTimezone() : GitBlitWebApp.get().getTimezone(); | |||
} | |||
protected class ChartValue implements Serializable, Comparable<ChartValue> { | |||
@@ -104,4 +126,20 @@ public abstract class GoogleChart implements Serializable { | |||
return 0; | |||
} | |||
} | |||
public String getDateFormat() { | |||
return dateFormat; | |||
} | |||
public void setDateFormat(String dateFormat) { | |||
this.dateFormat = dateFormat; | |||
} | |||
public String getClickUrl() { | |||
return clickUrl; | |||
} | |||
public void setClickUrl(String clickUrl) { | |||
this.clickUrl = clickUrl; | |||
} | |||
} |
@@ -0,0 +1,48 @@ | |||
/* | |||
* Copyright 2011 gitblit.com. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package com.gitblit.wicket.charting; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import org.apache.wicket.markup.html.IHeaderContributor; | |||
/** | |||
* Abstract parent class for Flotr2 Charts | |||
* | |||
* @author Tim Ryan | |||
* | |||
*/ | |||
public abstract class Charts implements IHeaderContributor { | |||
private static final long serialVersionUID = 1L; | |||
public final List<Chart> charts = new ArrayList<Chart>(); | |||
public void addChart(Chart chart) { | |||
charts.add(chart); | |||
} | |||
protected void line(StringBuilder sb, String line) { | |||
sb.append(line); | |||
sb.append('\n'); | |||
} | |||
public abstract Chart createPieChart(String tagId, String title, String keyName, String valueName); | |||
public abstract Chart createLineChart(String tagId, String title, String keyName, String valueName); | |||
public abstract Chart createBarChart(String tagId, String title, String keyName, String valueName); | |||
} |
@@ -0,0 +1,167 @@ | |||
/* | |||
* Copyright 2011 gitblit.com. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package com.gitblit.wicket.charting; | |||
import java.text.MessageFormat; | |||
import java.text.SimpleDateFormat; | |||
import java.util.Collections; | |||
import java.util.Comparator; | |||
import java.util.Date; | |||
/** | |||
* Implementation of a Bar chart using the flotr2 library | |||
* | |||
* @author Tim Ryan | |||
* | |||
*/ | |||
public class Flotr2BarChart extends Chart { | |||
private static final long serialVersionUID = 1L; | |||
boolean xAxisIsDate = false; | |||
public Flotr2BarChart(String tagId, String title, String keyName, | |||
String valueName) { | |||
super(tagId, title, keyName, valueName); | |||
} | |||
@Override | |||
protected void appendChart(StringBuilder sb) { | |||
String dName = "data_" + dataName; | |||
sb.append("var labels_" + dataName + " = ["); | |||
if(xAxisIsDate){ | |||
// Generate labels for the dates | |||
SimpleDateFormat df = new SimpleDateFormat(dateFormat); | |||
df.setTimeZone(getTimeZone()); | |||
// Sort the values first | |||
Collections.sort(values, new Comparator<ChartValue>() { | |||
public int compare(ChartValue o1, ChartValue o2) { | |||
long long1 = Long.parseLong(o1.name); | |||
long long2 = Long.parseLong(o2.name); | |||
return (int) (long2 - long1); | |||
} | |||
}); | |||
for (int i = 0; i < values.size(); i++) { | |||
ChartValue value = values.get(i); | |||
Date date = new Date(Long.parseLong(value.name)); | |||
String label = df.format(date); | |||
if(i > 0){ | |||
sb.append(","); | |||
} | |||
sb.append("[\"" + label + "\", " + value.name + "]"); | |||
} | |||
} | |||
else { | |||
for (int i = 0; i < values.size(); i++) { | |||
ChartValue value = values.get(i); | |||
if(i > 0){ | |||
sb.append(","); | |||
} | |||
sb.append("\"" + value.name + "\""); | |||
} | |||
} | |||
line(sb, "];"); | |||
line(sb, MessageFormat.format("var {0} = Flotr.draw(document.getElementById(''{1}''),", dName, tagId)); | |||
// Add the data | |||
line(sb, "["); | |||
line(sb, "{ data : [ "); | |||
for (int i = 0; i < values.size(); i++) { | |||
ChartValue value = values.get(i); | |||
if(i > 0){ | |||
sb.append(","); | |||
} | |||
if(xAxisIsDate){ | |||
line(sb, MessageFormat.format("[{0}, {1}] ", value.name, Float.toString(value.value))); | |||
} | |||
else { | |||
line(sb, MessageFormat.format("[{0}, {1}] ", Integer.toString(i), Float.toString(value.value))); | |||
} | |||
} | |||
line(sb, MessageFormat.format(" ], label : ''{0}'', color: ''#FF9900'' '}'", valueName)); | |||
line(sb, "]"); | |||
// Add the options | |||
line(sb, ", {"); | |||
if(title != null && title.isEmpty() == false){ | |||
line(sb, MessageFormat.format("title : ''{0}'',", title)); | |||
} | |||
line(sb, "bars : {"); | |||
line(sb, " show : true,"); | |||
line(sb, " horizontal : false,"); | |||
line(sb, " barWidth : 1"); | |||
line(sb, "},"); | |||
line(sb, "points: { show: false },"); | |||
line(sb, "mouse: {"); | |||
line(sb, " track: true,"); | |||
line(sb, " lineColor: '#002060',"); | |||
line(sb, " position: 'ne',"); | |||
line(sb, " trackFormatter: function (obj) {"); | |||
line(sb, " return labels_" + dataName + "[obj.index] + ': ' + parseInt(obj.y) + ' ' + obj.series.label;"); | |||
line(sb, " }"); | |||
line(sb, "},"); | |||
line(sb, "xaxis: {"); | |||
line(sb, " showLabels: true,"); | |||
line(sb, " showMinorLabels: false,"); | |||
line(sb, " tickFormatter: function (x) {"); | |||
line(sb, " var index = parseInt(x);"); | |||
line(sb, " if(x % 1 == 0 && labels_" + dataName + "[index])"); | |||
line(sb, " return labels_" + dataName + "[index];"); | |||
line(sb, " return \"\";"); | |||
line(sb, " },"); | |||
line(sb, " margin: 10"); | |||
line(sb, "},"); | |||
line(sb, "yaxis: {"); | |||
line(sb, " showLabels: false,"); | |||
line(sb, " showMinorLabels: false,"); | |||
line(sb, " tickDecimals: 0,"); | |||
line(sb, " margin: 10"); | |||
line(sb, "},"); | |||
line(sb, "grid: {"); | |||
line(sb, " verticalLines: false,"); | |||
line(sb, " minorVerticalLines: null,"); | |||
line(sb, " horizontalLines: true,"); | |||
line(sb, " minorHorizontalLines: null,"); | |||
line(sb, " outlineWidth: 1,"); | |||
line(sb, " outline: 's'"); | |||
line(sb, "},"); | |||
line(sb, "legend: {"); | |||
line(sb, " show: false"); | |||
line(sb, "}"); | |||
line(sb, "});"); | |||
} | |||
@Override | |||
public void addValue(Date date, int value) { | |||
xAxisIsDate = true; | |||
String name = String.valueOf(date.getTime()); | |||
super.addValue(name, value); | |||
} | |||
} |
@@ -0,0 +1,76 @@ | |||
/* | |||
* Copyright 2011 gitblit.com. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package com.gitblit.wicket.charting; | |||
import javax.servlet.ServletContext; | |||
import org.apache.wicket.markup.html.IHeaderResponse; | |||
import org.apache.wicket.protocol.http.WebApplication; | |||
/** | |||
* Concrete class for Flotr2 charts | |||
* | |||
* @author Tim Ryan | |||
* | |||
*/ | |||
public class Flotr2Charts extends Charts { | |||
private static final long serialVersionUID = 1L; | |||
@Override | |||
public void renderHead(IHeaderResponse response) { | |||
// add Google Chart JS API reference | |||
ServletContext servletContext = WebApplication.get().getServletContext(); | |||
String contextPath = servletContext.getContextPath(); | |||
response.renderJavascriptReference(contextPath + "/bootstrap/js/jquery.js"); | |||
response.renderJavascriptReference(contextPath + "/flotr2/flotr2.min.js"); | |||
response.renderCSSReference(contextPath + "/flotr2/flotr2.custom.css"); | |||
// prepare draw chart function | |||
StringBuilder sb = new StringBuilder(); | |||
line(sb, "$( document ).ready(function() {"); | |||
// add charts to header | |||
for (Chart chart : charts) { | |||
chart.appendChart(sb); | |||
} | |||
// end draw chart function | |||
line(sb, "});"); | |||
response.renderJavascript(sb.toString(), null); | |||
} | |||
@Override | |||
public Chart createPieChart(String tagId, String title, String keyName, | |||
String valueName) { | |||
return new Flotr2PieChart(tagId, title, keyName, valueName); | |||
} | |||
@Override | |||
public Chart createLineChart(String tagId, String title, String keyName, | |||
String valueName) { | |||
return new Flotr2LineChart(tagId, title, keyName, valueName); | |||
} | |||
@Override | |||
public Chart createBarChart(String tagId, String title, String keyName, | |||
String valueName) { | |||
return new Flotr2BarChart(tagId, title, keyName, valueName); | |||
} | |||
} |
@@ -0,0 +1,150 @@ | |||
/* | |||
* Copyright 2011 gitblit.com. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package com.gitblit.wicket.charting; | |||
import java.text.MessageFormat; | |||
import java.text.SimpleDateFormat; | |||
import java.util.Date; | |||
/** | |||
* Implementation of a Line chart using the flotr2 library | |||
* | |||
* @author Tim Ryan | |||
* | |||
*/ | |||
public class Flotr2LineChart extends Chart { | |||
private static final long serialVersionUID = 1L; | |||
boolean xAxisIsDate = false; | |||
public Flotr2LineChart(String tagId, String title, String keyName, | |||
String valueName) { | |||
super(tagId, title, keyName, valueName); | |||
} | |||
@Override | |||
protected void appendChart(StringBuilder sb) { | |||
String dName = "data_" + dataName; | |||
sb.append("var labels_" + dataName + " = ["); | |||
if(xAxisIsDate){ | |||
// Generate labels for the dates | |||
SimpleDateFormat df = new SimpleDateFormat(dateFormat); | |||
df.setTimeZone(getTimeZone()); | |||
for (int i = 0; i < values.size(); i++) { | |||
ChartValue value = values.get(i); | |||
Date date = new Date(Long.parseLong(value.name)); | |||
String label = df.format(date); | |||
if(i > 0){ | |||
sb.append(","); | |||
} | |||
sb.append("\"" + label + "\""); | |||
} | |||
} | |||
else { | |||
for (int i = 0; i < values.size(); i++) { | |||
ChartValue value = values.get(i); | |||
if(i > 0){ | |||
sb.append(","); | |||
} | |||
sb.append("\"" + value.name + "\""); | |||
} | |||
} | |||
line(sb, "];"); | |||
line(sb, MessageFormat.format("var {0} = Flotr.draw(document.getElementById(''{1}''),", dName, tagId)); | |||
// Add the data | |||
line(sb, "["); | |||
line(sb, "{ data : [ "); | |||
for (int i = 0; i < values.size(); i++) { | |||
ChartValue value = values.get(i); | |||
if(i > 0){ | |||
sb.append(","); | |||
} | |||
line(sb, MessageFormat.format("[{0}, {1}] ", value.name, Float.toString(value.value))); | |||
} | |||
line(sb, MessageFormat.format(" ], label : ''{0}'', lines : '{' show : true '}', color: ''#ff9900'' '}'", valueName)); | |||
if(highlights.size() > 0){ | |||
// get the highlights | |||
line(sb, ", { data : [ "); | |||
for (int i = 0; i < highlights.size(); i++) { | |||
ChartValue value = highlights.get(i); | |||
if(i > 0){ | |||
sb.append(","); | |||
} | |||
line(sb, MessageFormat.format("[{0}, {1}] ", value.name, Float.toString(value.value))); | |||
} | |||
line(sb, MessageFormat.format(" ], label : ''{0}'', points : '{' show : true, fill: true, fillColor:''#002060'' '}', color: ''#ff9900'' '}'", valueName)); | |||
} | |||
line(sb, "]"); | |||
// Add the options | |||
line(sb, ", {"); | |||
if(title != null && title.isEmpty() == false){ | |||
line(sb, MessageFormat.format("title : ''{0}'',", title)); | |||
} | |||
line(sb, "mouse: {"); | |||
line(sb, " track: true,"); | |||
line(sb, " lineColor: '#002060',"); | |||
line(sb, " position: 'ne',"); | |||
line(sb, " trackFormatter: function (obj) {"); | |||
line(sb, " return labels_" + dataName + "[obj.index] + ': ' + parseInt(obj.y) + ' ' + obj.series.label;"); | |||
line(sb, " }"); | |||
line(sb, "},"); | |||
line(sb, "xaxis: {"); | |||
line(sb, " showLabels: false,"); | |||
line(sb, " showMinorLabels: false,"); | |||
line(sb, " autoscale: true,"); | |||
line(sb, " autoscaleMargin: 0,"); | |||
line(sb, " margin: 10"); | |||
line(sb, "},"); | |||
line(sb, "yaxis: {"); | |||
line(sb, " showLabels: false,"); | |||
line(sb, " showMinorLabels: false,"); | |||
line(sb, " tickDecimals: 0,"); | |||
line(sb, " autoscale: true,"); | |||
line(sb, " autoscaleMargin: 1,"); | |||
line(sb, " margin: 10"); | |||
line(sb, "},"); | |||
line(sb, "grid: {"); | |||
line(sb, " verticalLines: false,"); | |||
line(sb, " minorVerticalLines: null,"); | |||
line(sb, " horizontalLines: true,"); | |||
line(sb, " minorHorizontalLines: null,"); | |||
line(sb, " outlineWidth: 1,"); | |||
line(sb, " outline: 's'"); | |||
line(sb, "},"); | |||
line(sb, "legend: {"); | |||
line(sb, " show: false"); | |||
line(sb, "}"); | |||
line(sb, "});"); | |||
} | |||
@Override | |||
public void addValue(Date date, int value) { | |||
xAxisIsDate = true; | |||
super.addValue(date, value); | |||
} | |||
} |
@@ -0,0 +1,112 @@ | |||
/* | |||
* Copyright 2011 gitblit.com. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package com.gitblit.wicket.charting; | |||
import java.text.MessageFormat; | |||
import com.gitblit.utils.StringUtils; | |||
/** | |||
* Implementation of a Pie chart using the flotr2 library | |||
* | |||
* @author Tim Ryan | |||
* | |||
*/ | |||
public class Flotr2PieChart extends Chart { | |||
private static final long serialVersionUID = 1L; | |||
public Flotr2PieChart(String tagId, String title, String keyName, String valueName) { | |||
super(tagId, title, keyName, valueName); | |||
} | |||
@Override | |||
protected void appendChart(StringBuilder sb) { | |||
String dName = "data_" + dataName; | |||
line(sb, "var selected_" + dataName + " = null;"); | |||
line(sb, MessageFormat.format("var {0} = Flotr.draw(document.getElementById(''{1}''),", dName, tagId)); | |||
// Add the data | |||
line(sb, "["); | |||
for (int i = 0; i < values.size(); i++) { | |||
ChartValue value = values.get(i); | |||
if(i > 0){ | |||
sb.append(","); | |||
} | |||
line(sb, MessageFormat.format("'{'data : [ [0, {0}] ], label : ''{1}'', color: ''{2}'' '}'", Float.toString(value.value), value.name, StringUtils.getColor(value.name))); | |||
} | |||
line(sb, "]"); | |||
// Add the options | |||
line(sb, ", {"); | |||
line(sb, MessageFormat.format("title : ''{0}'',", title)); | |||
line(sb, "fontSize : 2,"); | |||
line(sb, "pie : {"); | |||
line(sb, " show : true,"); | |||
line(sb, " labelFormatter : function (pie, slice) {"); | |||
line(sb, " if(slice / pie > .05)"); | |||
line(sb, " return Math.round(slice / pie * 100).toString() + \"%\";"); | |||
line(sb, " }"); | |||
line(sb, "}"); | |||
line(sb, ", mouse: {"); | |||
line(sb, " track: true,"); | |||
line(sb, " lineColor: '#002060',"); | |||
line(sb, " trackFormatter: function (obj)"); | |||
line(sb, " {"); | |||
line(sb, " selected_" + dataName + " = obj.series.label;"); | |||
line(sb, " return obj.series.label + \": \" + parseInt(obj.y) + \" (\" + Math.round(obj.fraction * 100) + \"%)\";" ); | |||
line(sb, " }"); | |||
line(sb, "}"); | |||
line(sb, ", xaxis: {"); | |||
line(sb, " margin: false,"); | |||
line(sb, " showLabels: false,"); | |||
line(sb, " showMinorLabels: false"); | |||
line(sb, "}"); | |||
line(sb, ", yaxis: {"); | |||
line(sb, " margin: false,"); | |||
line(sb, " min: 20,"); | |||
line(sb, " showLabels: false,"); | |||
line(sb, " showMinorLabels: false"); | |||
line(sb, "}"); | |||
line(sb, ", grid: {"); | |||
line(sb, " verticalLines: false,"); | |||
line(sb, " minorVerticalLines: null,"); | |||
line(sb, " horizontalLines: false,"); | |||
line(sb, " minorHorizontalLines: null,"); | |||
line(sb, " outlineWidth: 0"); | |||
line(sb, "}"); | |||
line(sb, ", legend: {"); | |||
if(showLegend){ | |||
line(sb, " show: true"); | |||
} | |||
else { | |||
line(sb, " show: false"); | |||
} | |||
line(sb, "}"); | |||
line(sb, "});"); | |||
if(clickUrl != null && clickUrl.isEmpty() == false){ | |||
line(sb, MessageFormat.format("Flotr.EventAdapter.observe(document.getElementById(''{0}''), ''flotr:click'', function (mouse, a, b, c) '{'", tagId)); | |||
line(sb, " window.location.href = \"" + clickUrl + "\" + selected_" + dataName + ";"); | |||
line(sb, "});"); | |||
} | |||
} | |||
} |
@@ -1,67 +0,0 @@ | |||
/* | |||
Copyright 2011 gitblit.com. | |||
Licensed under the Apache License, Version 2.0 (the "License"); | |||
you may not use this file except in compliance with the License. | |||
You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
*/ | |||
package com.gitblit.wicket.charting; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import org.apache.wicket.markup.html.IHeaderContributor; | |||
import org.apache.wicket.markup.html.IHeaderResponse; | |||
/** | |||
* The Google Visualization API provides interactive JavaScript based charts and | |||
* graphs. This class implements the JavaScript header necessary to display | |||
* complete graphs and charts. | |||
* | |||
* @author James Moger | |||
* | |||
*/ | |||
public class GoogleCharts implements IHeaderContributor { | |||
private static final long serialVersionUID = 1L; | |||
public final List<GoogleChart> charts = new ArrayList<GoogleChart>(); | |||
public void addChart(GoogleChart chart) { | |||
charts.add(chart); | |||
} | |||
@Override | |||
public void renderHead(IHeaderResponse response) { | |||
// add Google Chart JS API reference | |||
response.renderJavascriptReference("https://www.google.com/jsapi"); | |||
// prepare draw chart function | |||
StringBuilder sb = new StringBuilder(); | |||
line(sb, "google.load(\"visualization\", \"1\", {packages:[\"corechart\"]});"); | |||
line(sb, "google.setOnLoadCallback(drawChart);"); | |||
line(sb, "function drawChart() {"); | |||
// add charts to header | |||
for (GoogleChart chart : charts) { | |||
chart.appendChart(sb); | |||
} | |||
// end draw chart function | |||
line(sb, "}"); | |||
response.renderJavascript(sb.toString(), null); | |||
} | |||
private void line(StringBuilder sb, String line) { | |||
sb.append(line); | |||
sb.append('\n'); | |||
} | |||
} |
@@ -1,60 +0,0 @@ | |||
/* | |||
* Copyright 2011 gitblit.com. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package com.gitblit.wicket.charting; | |||
import java.text.MessageFormat; | |||
/** | |||
* Builds an interactive line chart using the Visualization API. | |||
* | |||
* @author James Moger | |||
* | |||
*/ | |||
public class GoogleLineChart extends GoogleChart { | |||
private static final long serialVersionUID = 1L; | |||
public GoogleLineChart(String tagId, String title, String keyName, String valueName) { | |||
super(tagId, title, keyName, valueName); | |||
} | |||
@Override | |||
protected void appendChart(StringBuilder sb) { | |||
String dName = "data_" + dataName; | |||
line(sb, MessageFormat.format("var {0} = new google.visualization.DataTable();", dName)); | |||
line(sb, MessageFormat.format("{0}.addColumn(''string'', ''{1}'');", dName, keyName)); | |||
line(sb, MessageFormat.format("{0}.addColumn(''number'', ''{1}'');", dName, valueName)); | |||
line(sb, MessageFormat.format("{0}.addRows({1,number,0});", dName, values.size())); | |||
for (int i = 0; i < values.size(); i++) { | |||
ChartValue value = values.get(i); | |||
line(sb, MessageFormat.format("{0}.setValue({1,number,0}, 0, \"{2}\");", dName, i, | |||
value.name)); | |||
line(sb, MessageFormat.format("{0}.setValue({1,number,0}, 1, {2,number,0.0});", dName, | |||
i, value.value)); | |||
} | |||
String cName = "chart_" + dataName; | |||
line(sb, MessageFormat.format( | |||
"var {0} = new google.visualization.LineChart(document.getElementById(''{1}''));", | |||
cName, tagId)); | |||
line(sb, | |||
MessageFormat | |||
.format("{0}.draw({1}, '{'width: {2,number,0}, height: {3,number,0}, pointSize: 4, chartArea:'{'left:20,top:20'}', vAxis: '{' textPosition: ''none'' '}', legend: ''none'', title: ''{4}'' '}');", | |||
cName, dName, width, height, title)); | |||
line(sb, ""); | |||
} | |||
} |
@@ -1,86 +0,0 @@ | |||
/* | |||
* Copyright 2011 gitblit.com. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package com.gitblit.wicket.charting; | |||
import java.text.MessageFormat; | |||
import java.util.ArrayList; | |||
import java.util.Collections; | |||
import java.util.List; | |||
import com.gitblit.utils.StringUtils; | |||
/** | |||
* Builds an interactive pie chart using the Visualization API. | |||
* | |||
* @author James Moger | |||
* | |||
*/ | |||
public class GooglePieChart extends GoogleChart { | |||
private static final long serialVersionUID = 1L; | |||
public GooglePieChart(String tagId, String title, String keyName, String valueName) { | |||
super(tagId, title, keyName, valueName); | |||
} | |||
@Override | |||
protected void appendChart(StringBuilder sb) { | |||
// create dataset | |||
String dName = "data_" + dataName; | |||
line(sb, MessageFormat.format("var {0} = new google.visualization.DataTable();", dName)); | |||
line(sb, MessageFormat.format("{0}.addColumn(''string'', ''{1}'');", dName, keyName)); | |||
line(sb, MessageFormat.format("{0}.addColumn(''number'', ''{1}'');", dName, valueName)); | |||
line(sb, MessageFormat.format("{0}.addRows({1,number,0});", dName, values.size())); | |||
Collections.sort(values); | |||
List<ChartValue> list = new ArrayList<ChartValue>(); | |||
int maxSlices = 10; | |||
if (values.size() > maxSlices) { | |||
list.addAll(values.subList(0, maxSlices)); | |||
} else { | |||
list.addAll(values); | |||
} | |||
StringBuilder colors = new StringBuilder("colors:["); | |||
for (int i = 0; i < list.size(); i++) { | |||
ChartValue value = list.get(i); | |||
colors.append('\''); | |||
colors.append(StringUtils.getColor(value.name)); | |||
colors.append('\''); | |||
if (i < values.size() - 1) { | |||
colors.append(','); | |||
} | |||
line(sb, MessageFormat.format("{0}.setValue({1,number,0}, 0, \"{2}\");", dName, i, | |||
value.name)); | |||
line(sb, MessageFormat.format("{0}.setValue({1,number,0}, 1, {2,number,0.0});", dName, | |||
i, value.value)); | |||
} | |||
colors.append(']'); | |||
// instantiate chart | |||
String cName = "chart_" + dataName; | |||
line(sb, MessageFormat.format( | |||
"var {0} = new google.visualization.PieChart(document.getElementById(''{1}''));", | |||
cName, tagId)); | |||
line(sb, | |||
MessageFormat | |||
.format("{0}.draw({1}, '{' title: ''{4}'', {5}, legend: '{' position:''{6}'' '}' '}');", | |||
cName, dName, width, height, title, colors.toString(), showLegend ? "right" : "none")); | |||
line(sb, ""); | |||
} | |||
} |
@@ -1,633 +0,0 @@ | |||
/* | |||
* Copyright 2007 Daniel Spiewak. | |||
* Copyright 2013 gitblit.com. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package com.gitblit.wicket.charting; | |||
import java.awt.Color; | |||
import java.awt.Dimension; | |||
import java.io.Serializable; | |||
import java.lang.reflect.InvocationTargetException; | |||
import java.util.concurrent.locks.ReadWriteLock; | |||
import java.util.concurrent.locks.ReentrantReadWriteLock; | |||
import org.apache.wicket.markup.ComponentTag; | |||
import org.apache.wicket.markup.html.WebComponent; | |||
import org.wicketstuff.googlecharts.ChartDataEncoding; | |||
import org.wicketstuff.googlecharts.IChartAxis; | |||
import org.wicketstuff.googlecharts.IChartData; | |||
import org.wicketstuff.googlecharts.IChartFill; | |||
import org.wicketstuff.googlecharts.IChartGrid; | |||
import org.wicketstuff.googlecharts.IChartProvider; | |||
import org.wicketstuff.googlecharts.IFillArea; | |||
import org.wicketstuff.googlecharts.ILineStyle; | |||
import org.wicketstuff.googlecharts.ILinearGradientFill; | |||
import org.wicketstuff.googlecharts.ILinearStripesFill; | |||
import org.wicketstuff.googlecharts.IRangeMarker; | |||
import org.wicketstuff.googlecharts.IShapeMarker; | |||
import org.wicketstuff.googlecharts.ISolidFill; | |||
import org.wicketstuff.googlecharts.Range; | |||
/** | |||
* This is a fork of org.wicketstuff.googlecharts.Chart whose only purpose | |||
* is to build https urls instead of http urls. | |||
* | |||
* @author Daniel Spiewak | |||
* @author James Moger | |||
*/ | |||
public class SecureChart extends WebComponent implements Serializable { | |||
private static final long serialVersionUID = 6286305912682861488L; | |||
private IChartProvider provider; | |||
private StringBuilder url; | |||
private final ReadWriteLock lock = new ReentrantReadWriteLock(); | |||
public SecureChart(String id, IChartProvider provider) { | |||
super(id); | |||
this.provider = provider; | |||
} | |||
public void invalidate() { | |||
lock.writeLock().lock(); | |||
try { | |||
url = null; | |||
} finally { | |||
lock.writeLock().unlock(); | |||
} | |||
} | |||
public CharSequence constructURL() { | |||
lock.writeLock().lock(); | |||
try { | |||
if (url != null) { | |||
return url; | |||
} | |||
url = new StringBuilder("https://chart.googleapis.com/chart?"); | |||
addParameter(url, "chs", render(provider.getSize())); | |||
addParameter(url, "chd", render(provider.getData())); | |||
addParameter(url, "cht", render(provider.getType())); | |||
addParameter(url, "chbh", render(provider.getBarWidth(), provider.getBarGroupSpacing())); | |||
addParameter(url, "chtt", render(provider.getTitle())); | |||
addParameter(url, "chdl", render(provider.getLegend())); | |||
addParameter(url, "chco", render(provider.getColors())); | |||
IChartFill bgFill = provider.getBackgroundFill(); | |||
IChartFill fgFill = provider.getChartFill(); | |||
StringBuilder fillParam = new StringBuilder(); | |||
if (bgFill != null) { | |||
fillParam.append("bg,").append(render(bgFill)); | |||
} | |||
if (fgFill != null) { | |||
if (fillParam.length() > 0) { | |||
fillParam.append('|'); | |||
} | |||
fillParam.append("c,").append(render(fgFill)); | |||
} | |||
if (fillParam.toString().trim().equals("")) { | |||
fillParam = null; | |||
} | |||
addParameter(url, "chf", fillParam); | |||
IChartAxis[] axes = provider.getAxes(); | |||
addParameter(url, "chxt", renderTypes(axes)); | |||
addParameter(url, "chxl", renderLabels(axes)); | |||
addParameter(url, "chxp", renderPositions(axes)); | |||
addParameter(url, "chxr", renderRanges(axes)); | |||
addParameter(url, "chxs", renderStyles(axes)); | |||
addParameter(url, "chg", render(provider.getGrid())); | |||
addParameter(url, "chm", render(provider.getShapeMarkers())); | |||
addParameter(url, "chm", render(provider.getRangeMarkers())); | |||
addParameter(url, "chls", render(provider.getLineStyles())); | |||
addParameter(url, "chm", render(provider.getFillAreas())); | |||
addParameter(url, "chl", render(provider.getPieLabels())); | |||
return url; | |||
} finally { | |||
lock.writeLock().unlock(); | |||
} | |||
} | |||
private void addParameter(StringBuilder url, CharSequence param, CharSequence value) { | |||
if (value == null || value.length() == 0) { | |||
return; | |||
} | |||
if (url.charAt(url.length() - 1) != '?') { | |||
url.append('&'); | |||
} | |||
url.append(param).append('=').append(value); | |||
} | |||
private CharSequence convert(ChartDataEncoding encoding, double value, double max) { | |||
switch (encoding) { | |||
case TEXT: | |||
return SecureChartDataEncoding.TEXT.convert(value, max); | |||
case EXTENDED: | |||
return SecureChartDataEncoding.EXTENDED.convert(value, max); | |||
case SIMPLE: | |||
default: | |||
return SecureChartDataEncoding.SIMPLE.convert(value, max); | |||
} | |||
} | |||
private CharSequence render(Dimension dim) { | |||
if (dim == null) { | |||
return null; | |||
} | |||
return new StringBuilder().append(dim.width).append('x').append(dim.height); | |||
} | |||
private CharSequence render(IChartData data) { | |||
if (data == null) { | |||
return null; | |||
} | |||
ChartDataEncoding encoding = data.getEncoding(); | |||
StringBuilder back = new StringBuilder(); | |||
back.append(render(encoding)).append(':'); | |||
for (double[] set : data.getData()) { | |||
if (set == null || set.length == 0) { | |||
back.append(convert(encoding, -1, data.getMax())); | |||
} else { | |||
for (double value : set) { | |||
back.append(convert(encoding, value, data.getMax())).append(encoding.getValueSeparator()); | |||
} | |||
if (back.substring(back.length() - encoding.getValueSeparator().length(), | |||
back.length()).equals(encoding.getValueSeparator())) { | |||
back.setLength(back.length() - encoding.getValueSeparator().length()); | |||
} | |||
} | |||
back.append(encoding.getSetSeparator()); | |||
} | |||
if (back.substring(back.length() - encoding.getSetSeparator().length(), | |||
back.length()).equals(encoding.getSetSeparator())) { | |||
back.setLength(back.length() - encoding.getSetSeparator().length()); | |||
} | |||
return back; | |||
} | |||
private CharSequence render(Enum<?> value) { | |||
if (value == null) { | |||
return null; | |||
} | |||
try { | |||
Object back = value.getClass().getMethod("getRendering").invoke(value); | |||
if (back != null) { | |||
return back.toString(); | |||
} | |||
} catch (IllegalArgumentException e) { | |||
} catch (SecurityException e) { | |||
} catch (IllegalAccessException e) { | |||
} catch (InvocationTargetException e) { | |||
} catch (NoSuchMethodException e) { | |||
} | |||
return null; | |||
} | |||
private CharSequence render(int barWidth, int groupSpacing) { | |||
if (barWidth == -1) { | |||
return null; | |||
} | |||
StringBuilder back = new StringBuilder(barWidth); | |||
if (groupSpacing >= 0) { | |||
back.append(',').append(groupSpacing); | |||
} | |||
return back; | |||
} | |||
private CharSequence render(String[] values) { | |||
if (values == null) { | |||
return null; | |||
} | |||
StringBuilder back = new StringBuilder(); | |||
for (String value : values) { | |||
CharSequence toRender = render(value); | |||
if (toRender == null) { | |||
toRender = ""; | |||
} | |||
back.append(toRender).append('|'); | |||
} | |||
if (back.length() > 0) { | |||
back.setLength(back.length() - 1); | |||
} | |||
return back; | |||
} | |||
private CharSequence render(String value) { | |||
if (value == null) { | |||
return value; | |||
} | |||
StringBuilder back = new StringBuilder(); | |||
for (char c : value.toCharArray()) { | |||
if (c == ' ') { | |||
back.append('+'); | |||
} else { | |||
back.append(c); | |||
} | |||
} | |||
return back; | |||
} | |||
private CharSequence render(Color[] values) { | |||
if (values == null) { | |||
return null; | |||
} | |||
StringBuilder back = new StringBuilder(); | |||
for (Color value : values) { | |||
CharSequence toRender = render(value); | |||
if (toRender == null) { | |||
toRender = ""; | |||
} | |||
back.append(toRender).append(','); | |||
} | |||
if (back.length() > 0) { | |||
back.setLength(back.length() - 1); | |||
} | |||
return back; | |||
} | |||
private CharSequence render(Color value) { | |||
if (value == null) { | |||
return null; | |||
} | |||
StringBuilder back = new StringBuilder(); | |||
{ | |||
String toPad = Integer.toHexString(value.getRed()); | |||
if (toPad.length() == 1) { | |||
back.append(0); | |||
} | |||
back.append(toPad); | |||
} | |||
{ | |||
String toPad = Integer.toHexString(value.getGreen()); | |||
if (toPad.length() == 1) { | |||
back.append(0); | |||
} | |||
back.append(toPad); | |||
} | |||
{ | |||
String toPad = Integer.toHexString(value.getBlue()); | |||
if (toPad.length() == 1) { | |||
back.append(0); | |||
} | |||
back.append(toPad); | |||
} | |||
{ | |||
String toPad = Integer.toHexString(value.getAlpha()); | |||
if (toPad.length() == 1) { | |||
back.append(0); | |||
} | |||
back.append(toPad); | |||
} | |||
return back; | |||
} | |||
private CharSequence render(IChartFill fill) { | |||
if (fill == null) { | |||
return null; | |||
} | |||
StringBuilder back = new StringBuilder(); | |||
if (fill instanceof ISolidFill) { | |||
ISolidFill solidFill = (ISolidFill) fill; | |||
back.append("s,"); | |||
back.append(render(solidFill.getColor())); | |||
} else if (fill instanceof ILinearGradientFill) { | |||
ILinearGradientFill gradientFill = (ILinearGradientFill) fill; | |||
back.append("lg,").append(gradientFill.getAngle()).append(','); | |||
Color[] colors = gradientFill.getColors(); | |||
double[] offsets = gradientFill.getOffsets(); | |||
for (int i = 0; i < colors.length; i++) { | |||
back.append(render(colors[i])).append(',').append(offsets[i]).append(','); | |||
} | |||
back.setLength(back.length() - 1); | |||
} else if (fill instanceof ILinearStripesFill) { | |||
ILinearStripesFill stripesFill = (ILinearStripesFill) fill; | |||
back.append("ls,").append(stripesFill.getAngle()).append(','); | |||
Color[] colors = stripesFill.getColors(); | |||
double[] widths = stripesFill.getWidths(); | |||
for (int i = 0; i < colors.length; i++) { | |||
back.append(render(colors[i])).append(',').append(widths[i]).append(','); | |||
} | |||
back.setLength(back.length() - 1); | |||
} else { | |||
return null; | |||
} | |||
return back; | |||
} | |||
private CharSequence renderTypes(IChartAxis[] axes) { | |||
if (axes == null) { | |||
return null; | |||
} | |||
StringBuilder back = new StringBuilder(); | |||
for (IChartAxis axis : axes) { | |||
back.append(render(axis.getType())).append(','); | |||
} | |||
if (back.length() > 0) { | |||
back.setLength(back.length() - 1); | |||
} | |||
return back; | |||
} | |||
private CharSequence renderLabels(IChartAxis[] axes) { | |||
if (axes == null) { | |||
return null; | |||
} | |||
StringBuilder back = new StringBuilder(); | |||
for (int i = 0; i < axes.length; i++) { | |||
if (axes[i] == null || axes[i].getLabels() == null) { | |||
continue; | |||
} | |||
back.append(i).append(":|"); | |||
for (String label : axes[i].getLabels()) { | |||
if (label == null) { | |||
back.append('|'); | |||
continue; | |||
} | |||
back.append(render(label)).append('|'); | |||
} | |||
if (i == axes.length - 1) { | |||
back.setLength(back.length() - 1); | |||
} | |||
} | |||
return back; | |||
} | |||
private CharSequence renderPositions(IChartAxis[] axes) { | |||
if (axes == null) { | |||
return null; | |||
} | |||
StringBuilder back = new StringBuilder(); | |||
for (int i = 0; i < axes.length; i++) { | |||
if (axes[i] == null || axes[i].getPositions() == null) { | |||
continue; | |||
} | |||
back.append(i).append(','); | |||
for (double position : axes[i].getPositions()) { | |||
back.append(position).append(','); | |||
} | |||
back.setLength(back.length() - 1); | |||
back.append('|'); | |||
} | |||
if (back.length() > 0) { | |||
back.setLength(back.length() - 1); | |||
} | |||
return back; | |||
} | |||
private CharSequence renderRanges(IChartAxis[] axes) { | |||
if (axes == null) { | |||
return null; | |||
} | |||
StringBuilder back = new StringBuilder(); | |||
for (int i = 0; i < axes.length; i++) { | |||
if (axes[i] == null || axes[i].getRange() == null) { | |||
continue; | |||
} | |||
back.append(i).append(','); | |||
Range range = axes[i].getRange(); | |||
back.append(range.getStart()).append(',').append(range.getEnd()).append('|'); | |||
} | |||
if (back.length() > 0) { | |||
back.setLength(back.length() - 1); | |||
} | |||
return back; | |||
} | |||
private CharSequence renderStyles(IChartAxis[] axes) { | |||
if (axes == null) { | |||
return null; | |||
} | |||
StringBuilder back = new StringBuilder(); | |||
for (int i = 0; i < axes.length; i++) { | |||
if (axes[i] == null || axes[i].getColor() == null | |||
|| axes[i].getFontSize() < 0 || axes[i].getAlignment() == null) { | |||
continue; | |||
} | |||
back.append(i).append(','); | |||
back.append(render(axes[i].getColor())).append(','); | |||
back.append(axes[i].getFontSize()).append(','); | |||
back.append(render(axes[i].getAlignment())).append('|'); | |||
} | |||
if (back.length() > 0) { | |||
back.setLength(back.length() - 1); | |||
} | |||
return back; | |||
} | |||
private CharSequence render(IChartGrid grid) { | |||
if (grid == null) { | |||
return null; | |||
} | |||
StringBuilder back = new StringBuilder(); | |||
back.append(grid.getXStepSize()).append(','); | |||
back.append(grid.getYStepSize()); | |||
if (grid.getSegmentLength() >= 0) { | |||
back.append(',').append(grid.getSegmentLength()); | |||
back.append(',').append(grid.getBlankLength()); | |||
} | |||
return back; | |||
} | |||
private CharSequence render(IShapeMarker[] markers) { | |||
if (markers == null) { | |||
return null; | |||
} | |||
StringBuilder back = new StringBuilder(); | |||
for (IShapeMarker marker : markers) { | |||
back.append(render(marker.getType())).append(','); | |||
back.append(render(marker.getColor())).append(','); | |||
back.append(marker.getIndex()).append(','); | |||
back.append(marker.getPoint()).append(','); | |||
back.append(marker.getSize()).append('|'); | |||
} | |||
if (back.length() > 0) { | |||
back.setLength(back.length() - 1); | |||
} | |||
return back; | |||
} | |||
private CharSequence render(IRangeMarker[] markers) { | |||
if (markers == null) { | |||
return null; | |||
} | |||
StringBuilder back = new StringBuilder(); | |||
for (IRangeMarker marker : markers) { | |||
back.append(render(marker.getType())).append(','); | |||
back.append(render(marker.getColor())).append(','); | |||
back.append(0).append(','); | |||
back.append(marker.getStart()).append(','); | |||
back.append(marker.getEnd()).append('|'); | |||
} | |||
if (back.length() > 0) { | |||
back.setLength(back.length() - 1); | |||
} | |||
return back; | |||
} | |||
private CharSequence render(IFillArea[] areas) { | |||
if (areas == null) { | |||
return null; | |||
} | |||
StringBuilder back = new StringBuilder(); | |||
for (IFillArea area : areas) { | |||
back.append(render(area.getType())).append(','); | |||
back.append(render(area.getColor())).append(','); | |||
back.append(area.getStartIndex()).append(','); | |||
back.append(area.getEndIndex()).append(','); | |||
back.append(0).append('|'); | |||
} | |||
if (back.length() > 0) { | |||
back.setLength(back.length() - 1); | |||
} | |||
return back; | |||
} | |||
private CharSequence render(ILineStyle[] styles) { | |||
if (styles == null) { | |||
return null; | |||
} | |||
StringBuilder back = new StringBuilder(); | |||
for (ILineStyle style : styles) { | |||
if (style == null) { | |||
back.append('|'); | |||
continue; | |||
} | |||
back.append(style.getThickness()).append(','); | |||
back.append(style.getSegmentLength()).append(','); | |||
back.append(style.getBlankLength()).append('|'); | |||
} | |||
if (back.length() > 0) { | |||
back.setLength(back.length() - 1); | |||
} | |||
return back; | |||
} | |||
@Override | |||
protected void onComponentTag(ComponentTag tag) { | |||
checkComponentTag(tag, "img"); | |||
super.onComponentTag(tag); | |||
tag.put("src", constructURL()); | |||
} | |||
} |
@@ -1,102 +0,0 @@ | |||
/* | |||
* Copyright 2007 Daniel Spiewak. | |||
* Copyright 2013 gitblit.com. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package com.gitblit.wicket.charting; | |||
/** | |||
* This class is a pristine fork of org.wicketstuff.googlecharts.ChartDataEncoding | |||
* to bring the package-protected convert methods to SecureChart. | |||
* | |||
* @author Daniel Spiewak | |||
*/ | |||
public enum SecureChartDataEncoding { | |||
SIMPLE("s", "", ",") { | |||
@Override | |||
CharSequence convert(double value, double max) { | |||
if (value < 0) { | |||
return "_"; | |||
} | |||
value = Math.round((CHARS.length() - 1) * value / max); | |||
if (value > CHARS.length() - 1) { | |||
throw new IllegalArgumentException(value + " is out of range for SIMPLE encoding"); | |||
} | |||
return Character.toString(CHARS.charAt((int) value)); | |||
} | |||
}, | |||
TEXT("t", ",", "|") { | |||
@Override | |||
CharSequence convert(double value, double max) { | |||
if (value < 0) { | |||
value = -1; | |||
} | |||
if (value > 100) { | |||
throw new IllegalArgumentException(value + " is out of range for TEXT encoding"); | |||
} | |||
return Double.toString(value); | |||
} | |||
}, | |||
EXTENDED("e", "", ",") { | |||
@Override | |||
CharSequence convert(double value, double max) { | |||
if (value < 0) { | |||
return "__"; | |||
} | |||
value = Math.round(value); | |||
if (value > (EXT_CHARS.length() - 1) * (EXT_CHARS.length() - 1)) { | |||
throw new IllegalArgumentException(value + " is out of range for EXTENDED encoding"); | |||
} | |||
int rem = (int) (value % EXT_CHARS.length()); | |||
int exp = (int) (value / EXT_CHARS.length()); | |||
return new StringBuilder().append(EXT_CHARS.charAt(exp)).append(EXT_CHARS.charAt(rem)); | |||
} | |||
}; | |||
private static final String CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; | |||
private static final String EXT_CHARS = CHARS + "-_."; | |||
private final String rendering, valueSeparator, setSeparator; | |||
private SecureChartDataEncoding(String rendering, String valueSeparator, String setSeparator) { | |||
this.rendering = rendering; | |||
this.valueSeparator = valueSeparator; | |||
this.setSeparator = setSeparator; | |||
} | |||
public String getRendering() { | |||
return rendering; | |||
} | |||
public String getValueSeparator() { | |||
return valueSeparator; | |||
} | |||
public String getSetSeparator() { | |||
return setSeparator; | |||
} | |||
abstract CharSequence convert(double value, double max); | |||
} |
@@ -41,10 +41,9 @@ import com.gitblit.wicket.PageRegistration; | |||
import com.gitblit.wicket.PageRegistration.DropDownMenuItem; | |||
import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration; | |||
import com.gitblit.wicket.WicketUtils; | |||
import com.gitblit.wicket.charting.GoogleChart; | |||
import com.gitblit.wicket.charting.GoogleCharts; | |||
import com.gitblit.wicket.charting.GoogleLineChart; | |||
import com.gitblit.wicket.charting.GooglePieChart; | |||
import com.gitblit.wicket.charting.Chart; | |||
import com.gitblit.wicket.charting.Charts; | |||
import com.gitblit.wicket.charting.Flotr2Charts; | |||
import com.gitblit.wicket.panels.ActivityPanel; | |||
/** | |||
@@ -118,7 +117,7 @@ public class ActivityPage extends RootPage { | |||
// create the activity charts | |||
if (app().settings().getBoolean(Keys.web.generateActivityGraph, true)) { | |||
GoogleCharts charts = createCharts(recentActivity); | |||
Charts charts = createCharts(recentActivity); | |||
add(new HeaderContributor(charts)); | |||
add(new Fragment("chartsPanel", "chartsFragment", this)); | |||
} else { | |||
@@ -166,7 +165,7 @@ public class ActivityPage extends RootPage { | |||
* @param recentActivity | |||
* @return | |||
*/ | |||
private GoogleCharts createCharts(List<Activity> recentActivity) { | |||
private Charts createCharts(List<Activity> recentActivity) { | |||
// activity metrics | |||
Map<String, Metric> repositoryMetrics = new HashMap<String, Metric>(); | |||
Map<String, Metric> authorMetrics = new HashMap<String, Metric>(); | |||
@@ -193,34 +192,36 @@ public class ActivityPage extends RootPage { | |||
} | |||
} | |||
// build google charts | |||
GoogleCharts charts = new GoogleCharts(); | |||
// build charts | |||
Charts charts = new Flotr2Charts(); | |||
// sort in reverse-chronological order and then reverse that | |||
Collections.sort(recentActivity); | |||
Collections.reverse(recentActivity); | |||
// daily line chart | |||
GoogleChart chart = new GoogleLineChart("chartDaily", getString("gb.dailyActivity"), "day", | |||
Chart chart = charts.createLineChart("chartDaily", getString("gb.dailyActivity"), "day", | |||
getString("gb.commits")); | |||
SimpleDateFormat df = new SimpleDateFormat("MMM dd"); | |||
df.setTimeZone(getTimeZone()); | |||
for (Activity metric : recentActivity) { | |||
chart.addValue(df.format(metric.startDate), metric.getCommitCount()); | |||
chart.addValue(metric.startDate, metric.getCommitCount()); | |||
} | |||
charts.addChart(chart); | |||
// active repositories pie chart | |||
chart = new GooglePieChart("chartRepositories", getString("gb.activeRepositories"), | |||
// active repositories pie chart | |||
chart = charts.createPieChart("chartRepositories", getString("gb.activeRepositories"), | |||
getString("gb.repository"), getString("gb.commits")); | |||
for (Metric metric : repositoryMetrics.values()) { | |||
chart.addValue(metric.name, metric.count); | |||
} | |||
chart.setShowLegend(false); | |||
String url = urlFor(SummaryPage.class, null).toString() + "?r="; | |||
chart.setClickUrl(url); | |||
charts.addChart(chart); | |||
// active authors pie chart | |||
chart = new GooglePieChart("chartAuthors", getString("gb.activeAuthors"), | |||
chart = charts.createPieChart("chartAuthors", getString("gb.activeAuthors"), | |||
getString("gb.author"), getString("gb.commits")); | |||
for (Metric metric : authorMetrics.values()) { | |||
chart.addValue(metric.name, metric.count); |
@@ -48,9 +48,9 @@ import com.gitblit.wicket.GitBlitWebApp; | |||
import com.gitblit.wicket.PageRegistration; | |||
import com.gitblit.wicket.PageRegistration.DropDownMenuItem; | |||
import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration; | |||
import com.gitblit.wicket.charting.GoogleChart; | |||
import com.gitblit.wicket.charting.GoogleCharts; | |||
import com.gitblit.wicket.charting.GooglePieChart; | |||
import com.gitblit.wicket.charting.Chart; | |||
import com.gitblit.wicket.charting.Charts; | |||
import com.gitblit.wicket.charting.Flotr2Charts; | |||
import com.gitblit.wicket.panels.DigestsPanel; | |||
import com.gitblit.wicket.panels.LinkPanel; | |||
@@ -218,19 +218,21 @@ public abstract class DashboardPage extends RootPage { | |||
if (app().settings().getBoolean(Keys.web.generateActivityGraph, true)) { | |||
// build google charts | |||
GoogleCharts charts = new GoogleCharts(); | |||
Charts charts = new Flotr2Charts(); | |||
// active repositories pie chart | |||
GoogleChart chart = new GooglePieChart("chartRepositories", getString("gb.activeRepositories"), | |||
Chart chart = charts.createPieChart("chartRepositories", getString("gb.activeRepositories"), | |||
getString("gb.repository"), getString("gb.commits")); | |||
for (Metric metric : repositoryMetrics.values()) { | |||
chart.addValue(metric.name, metric.count); | |||
} | |||
chart.setShowLegend(false); | |||
String url = urlFor(SummaryPage.class, null).toString() + "?r="; | |||
chart.setClickUrl(url); | |||
charts.addChart(chart); | |||
// active authors pie chart | |||
chart = new GooglePieChart("chartAuthors", getString("gb.activeAuthors"), | |||
chart = charts.createPieChart("chartAuthors", getString("gb.activeAuthors"), | |||
getString("gb.author"), getString("gb.commits")); | |||
for (Metric metric : authorMetrics.values()) { | |||
chart.addValue(metric.name, metric.count); |
@@ -13,7 +13,7 @@ | |||
<table style="width:100%;"> | |||
<tr> | |||
<!-- branch stats --> | |||
<td colspan=2> | |||
<td colspan="2"> | |||
<h2><wicket:message key="gb.stats"></wicket:message></h2> | |||
<span wicket:id="branchStats"></span> | |||
</td> | |||
@@ -22,19 +22,19 @@ | |||
<!-- commit activity trend --> | |||
<td> | |||
<h2><wicket:message key="gb.commitActivityTrend"></wicket:message></h2> | |||
<div><img wicket:id="commitsChart" /></div> | |||
<div style="width:400px; height:100px;" id="commitsChart"></div> | |||
</td> | |||
<!-- commit activity by day of week --> | |||
<td> | |||
<h2><wicket:message key="gb.commitActivityDOW"></wicket:message></h2> | |||
<div><img wicket:id="dayOfWeekChart" /></div> | |||
<div style="width:400px; height:100px;" id="dayOfWeekChart"></div> | |||
</td> | |||
</tr> | |||
<tr> | |||
<!-- commit activity by primary authors --> | |||
<td colspan=2> | |||
<h2><wicket:message key="gb.commitActivityAuthors"></wicket:message></h2> | |||
<div style="text-align: center;"><img wicket:id="authorsChart" /></div> | |||
<td colspan="2" > | |||
<h2 style="text-align: center;"><wicket:message key="gb.commitActivityAuthors"></wicket:message></h2> | |||
<div style="margin: 0px auto;width:800px; height:200px;" id="authorsChart"></div> | |||
</td> | |||
</tr> | |||
</table> |
@@ -15,27 +15,20 @@ | |||
*/ | |||
package com.gitblit.wicket.pages; | |||
import java.awt.Color; | |||
import java.awt.Dimension; | |||
import java.text.MessageFormat; | |||
import java.text.ParseException; | |||
import java.text.SimpleDateFormat; | |||
import java.util.ArrayList; | |||
import java.util.Calendar; | |||
import java.util.Collections; | |||
import java.util.Comparator; | |||
import java.util.Date; | |||
import java.util.List; | |||
import org.apache.wicket.PageParameters; | |||
import org.apache.wicket.behavior.HeaderContributor; | |||
import org.apache.wicket.markup.html.basic.Label; | |||
import org.eclipse.jgit.lib.Repository; | |||
import org.wicketstuff.googlecharts.ChartAxis; | |||
import org.wicketstuff.googlecharts.ChartAxisType; | |||
import org.wicketstuff.googlecharts.ChartProvider; | |||
import org.wicketstuff.googlecharts.ChartType; | |||
import org.wicketstuff.googlecharts.IChartData; | |||
import org.wicketstuff.googlecharts.LineStyle; | |||
import org.wicketstuff.googlecharts.MarkerType; | |||
import org.wicketstuff.googlecharts.ShapeMarker; | |||
import com.gitblit.models.Metric; | |||
import com.gitblit.utils.MetricUtils; | |||
@@ -43,7 +36,9 @@ import com.gitblit.utils.StringUtils; | |||
import com.gitblit.wicket.CacheControl; | |||
import com.gitblit.wicket.CacheControl.LastModified; | |||
import com.gitblit.wicket.WicketUtils; | |||
import com.gitblit.wicket.charting.SecureChart; | |||
import com.gitblit.wicket.charting.Chart; | |||
import com.gitblit.wicket.charting.Charts; | |||
import com.gitblit.wicket.charting.Flotr2Charts; | |||
@CacheControl(LastModified.REPOSITORY) | |||
public class MetricsPage extends RepositoryPage { | |||
@@ -66,73 +61,71 @@ public class MetricsPage extends RepositoryPage { | |||
MessageFormat.format(getString("gb.branchStats"), metricsTotal.count, | |||
metricsTotal.tag, getTimeUtils().duration(metricsTotal.duration)))); | |||
} | |||
insertLinePlot("commitsChart", metrics); | |||
insertBarPlot("dayOfWeekChart", getDayOfWeekMetrics(r, objectId)); | |||
insertPieChart("authorsChart", getAuthorMetrics(r, objectId)); | |||
Charts charts = new Flotr2Charts(); | |||
add(WicketUtils.newBlankImage("commitsChart")); | |||
add(WicketUtils.newBlankImage("dayOfWeekChart")); | |||
add(WicketUtils.newBlankImage("authorsChart")); | |||
createLineChart(charts, "commitsChart", metrics); | |||
createBarChart(charts, "dayOfWeekChart", getDayOfWeekMetrics(r, objectId)); | |||
createPieChart(charts, "authorsChart", getAuthorMetrics(r, objectId)); | |||
add(new HeaderContributor(charts)); | |||
} | |||
private void insertLinePlot(String wicketId, List<Metric> metrics) { | |||
private void createLineChart(Charts charts, String id, List<Metric> metrics) { | |||
if ((metrics != null) && (metrics.size() > 0)) { | |||
IChartData data = WicketUtils.getChartData(metrics); | |||
ChartProvider provider = new ChartProvider(new Dimension(400, 100), ChartType.LINE, | |||
data); | |||
ChartAxis dateAxis = new ChartAxis(ChartAxisType.BOTTOM); | |||
dateAxis.setLabels(new String[] { metrics.get(0).name, | |||
metrics.get(metrics.size() / 2).name, metrics.get(metrics.size() - 1).name }); | |||
provider.addAxis(dateAxis); | |||
ChartAxis commitAxis = new ChartAxis(ChartAxisType.LEFT); | |||
commitAxis.setLabels(new String[] { "", | |||
String.valueOf((int) WicketUtils.maxValue(metrics)) }); | |||
provider.addAxis(commitAxis); | |||
provider.setLineStyles(new LineStyle[] { new LineStyle(2, 4, 0), new LineStyle(0, 4, 1) }); | |||
provider.addShapeMarker(new ShapeMarker(MarkerType.CIRCLE, Color.decode("#002060"), 1, -1, 5)); | |||
add(new SecureChart(wicketId, provider)); | |||
} else { | |||
add(WicketUtils.newBlankImage(wicketId)); | |||
Chart chart = charts.createLineChart(id, "", "day", | |||
getString("gb.commits")); | |||
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd"); | |||
String displayFormat = "MMM dd"; | |||
if(metrics.size() > 0 && metrics.get(0).name.length() == 7){ | |||
df = new SimpleDateFormat("yyyy-MM"); | |||
displayFormat = "yyyy MMM"; | |||
} | |||
df.setTimeZone(getTimeZone()); | |||
chart.setDateFormat(displayFormat); | |||
for (Metric metric : metrics) { | |||
Date date; | |||
try { | |||
date = df.parse(metric.name); | |||
} catch (ParseException e) { | |||
logger.error("Unable to parse date: " + metric.name); | |||
return; | |||
} | |||
chart.addValue(date, (int)metric.count); | |||
if(metric.tag > 0 ){ | |||
chart.addHighlight(date, (int)metric.count); | |||
} | |||
} | |||
charts.addChart(chart); | |||
} | |||
} | |||
private void insertBarPlot(String wicketId, List<Metric> metrics) { | |||
private void createPieChart(Charts charts, String id, List<Metric> metrics) { | |||
if ((metrics != null) && (metrics.size() > 0)) { | |||
IChartData data = WicketUtils.getChartData(metrics); | |||
ChartProvider provider = new ChartProvider(new Dimension(400, 100), | |||
ChartType.BAR_VERTICAL_SET, data); | |||
ChartAxis dateAxis = new ChartAxis(ChartAxisType.BOTTOM); | |||
List<String> labels = new ArrayList<String>(); | |||
Chart chart = charts.createPieChart(id, "", "day", | |||
getString("gb.commits")); | |||
for (Metric metric : metrics) { | |||
labels.add(metric.name); | |||
chart.addValue(metric.name, (int)metric.count); | |||
} | |||
dateAxis.setLabels(labels.toArray(new String[labels.size()])); | |||
provider.addAxis(dateAxis); | |||
ChartAxis commitAxis = new ChartAxis(ChartAxisType.LEFT); | |||
commitAxis.setLabels(new String[] { "", | |||
String.valueOf((int) WicketUtils.maxValue(metrics)) }); | |||
provider.addAxis(commitAxis); | |||
add(new SecureChart(wicketId, provider)); | |||
} else { | |||
add(WicketUtils.newBlankImage(wicketId)); | |||
charts.addChart(chart); | |||
} | |||
} | |||
private void insertPieChart(String wicketId, List<Metric> metrics) { | |||
private void createBarChart(Charts charts, String id, List<Metric> metrics) { | |||
if ((metrics != null) && (metrics.size() > 0)) { | |||
IChartData data = WicketUtils.getChartData(metrics); | |||
List<String> labels = new ArrayList<String>(); | |||
Chart chart = charts.createBarChart(id, "", "day", | |||
getString("gb.commits")); | |||
for (Metric metric : metrics) { | |||
labels.add(metric.name); | |||
chart.addValue(metric.name, (int)metric.count); | |||
} | |||
ChartProvider provider = new ChartProvider(new Dimension(800, 200), ChartType.PIE, data); | |||
provider.setPieLabels(labels.toArray(new String[labels.size()])); | |||
add(new SecureChart(wicketId, provider)); | |||
} else { | |||
add(WicketUtils.newBlankImage(wicketId)); | |||
charts.addChart(chart); | |||
} | |||
} | |||
@@ -68,8 +68,8 @@ | |||
<wicket:fragment wicket:id="chartsFragment"> | |||
<table> | |||
<tr> | |||
<td><div id="chartRepositories" style="display:inline-block;width: 175px; height:175px"></div></td> | |||
<td><div id="chartAuthors" style="display:inline-block;width: 175px; height: 175px;"></div></td> | |||
<td><div id="chartRepositories" style="display:inline-block;width: 250px; height:175px"></div></td> | |||
<td><div id="chartAuthors" style="display:inline-block;width: 250px; height: 175px;"></div></td> | |||
</tr> | |||
</table> | |||
</wicket:fragment> |
@@ -37,9 +37,9 @@ import com.gitblit.wicket.CacheControl; | |||
import com.gitblit.wicket.CacheControl.LastModified; | |||
import com.gitblit.wicket.GitBlitWebSession; | |||
import com.gitblit.wicket.WicketUtils; | |||
import com.gitblit.wicket.charting.GoogleChart; | |||
import com.gitblit.wicket.charting.GoogleCharts; | |||
import com.gitblit.wicket.charting.GoogleLineChart; | |||
import com.gitblit.wicket.charting.Chart; | |||
import com.gitblit.wicket.charting.Charts; | |||
import com.gitblit.wicket.charting.Flotr2Charts; | |||
import com.gitblit.wicket.panels.BranchesPanel; | |||
import com.gitblit.wicket.panels.LinkPanel; | |||
import com.gitblit.wicket.panels.ReflogPanel; | |||
@@ -135,8 +135,10 @@ public class OverviewPage extends RepositoryPage { | |||
if ((metrics != null) && (metrics.size() > 0) | |||
&& app().settings().getBoolean(Keys.web.generateActivityGraph, true)) { | |||
Charts charts = new Flotr2Charts(); | |||
// daily line chart | |||
GoogleChart chart = new GoogleLineChart("chartDaily", "", "unit", | |||
Chart chart = charts.createLineChart("chartDaily", "", "unit", | |||
getString("gb.commits")); | |||
for (Metric metric : metrics) { | |||
chart.addValue(metric.name, metric.count); | |||
@@ -144,7 +146,6 @@ public class OverviewPage extends RepositoryPage { | |||
chart.setWidth(375); | |||
chart.setHeight(150); | |||
GoogleCharts charts = new GoogleCharts(); | |||
charts.addChart(chart); | |||
add(new HeaderContributor(charts)); | |||
} |
@@ -9,7 +9,7 @@ | |||
<div style="clear:both;"> | |||
<!-- Repository Activity Chart --> | |||
<div class="hidden-phone" style="float:right;"> | |||
<img class="activityGraph" wicket:id="commitsChart" /> | |||
<div style="width:290px; height:120px;" id="commitsChart"></div> | |||
</div> | |||
<!-- Repository info --> |
@@ -15,14 +15,17 @@ | |||
*/ | |||
package com.gitblit.wicket.pages; | |||
import java.awt.Color; | |||
import java.awt.Dimension; | |||
import java.text.MessageFormat; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import java.text.ParseException; | |||
import java.text.SimpleDateFormat; | |||
import java.util.Date; | |||
import org.apache.wicket.Component; | |||
import org.apache.wicket.PageParameters; | |||
import org.apache.wicket.behavior.HeaderContributor; | |||
import org.apache.wicket.markup.html.basic.Label; | |||
import org.apache.wicket.markup.html.link.BookmarkablePageLink; | |||
import org.apache.wicket.markup.html.panel.Fragment; | |||
@@ -31,14 +34,6 @@ import org.apache.wicket.markup.repeater.data.DataView; | |||
import org.apache.wicket.markup.repeater.data.ListDataProvider; | |||
import org.eclipse.jgit.lib.Repository; | |||
import org.eclipse.jgit.revwalk.RevCommit; | |||
import org.wicketstuff.googlecharts.ChartAxis; | |||
import org.wicketstuff.googlecharts.ChartAxisType; | |||
import org.wicketstuff.googlecharts.ChartProvider; | |||
import org.wicketstuff.googlecharts.ChartType; | |||
import org.wicketstuff.googlecharts.IChartData; | |||
import org.wicketstuff.googlecharts.LineStyle; | |||
import org.wicketstuff.googlecharts.MarkerType; | |||
import org.wicketstuff.googlecharts.ShapeMarker; | |||
import com.gitblit.Keys; | |||
import com.gitblit.models.Metric; | |||
@@ -53,7 +48,9 @@ import com.gitblit.wicket.MarkupProcessor; | |||
import com.gitblit.wicket.MarkupProcessor.MarkupDocument; | |||
import com.gitblit.wicket.MarkupProcessor.MarkupSyntax; | |||
import com.gitblit.wicket.WicketUtils; | |||
import com.gitblit.wicket.charting.SecureChart; | |||
import com.gitblit.wicket.charting.Chart; | |||
import com.gitblit.wicket.charting.Charts; | |||
import com.gitblit.wicket.charting.Flotr2Charts; | |||
import com.gitblit.wicket.panels.BranchesPanel; | |||
import com.gitblit.wicket.panels.LinkPanel; | |||
import com.gitblit.wicket.panels.LogPanel; | |||
@@ -159,38 +156,49 @@ public class SummaryPage extends RepositoryPage { | |||
// global, no readme on summary page | |||
add(new Label("readme").setVisible(false)); | |||
} | |||
// Display an activity line graph | |||
insertActivityGraph(metrics); | |||
Charts charts = createCharts(metrics); | |||
add(new HeaderContributor(charts)); | |||
} | |||
@Override | |||
protected String getPageName() { | |||
return getString("gb.summary"); | |||
} | |||
private void insertActivityGraph(List<Metric> metrics) { | |||
if ((metrics != null) && (metrics.size() > 0) | |||
&& app().settings().getBoolean(Keys.web.generateActivityGraph, true)) { | |||
IChartData data = WicketUtils.getChartData(metrics); | |||
ChartProvider provider = new ChartProvider(new Dimension(290, 100), ChartType.LINE, | |||
data); | |||
ChartAxis dateAxis = new ChartAxis(ChartAxisType.BOTTOM); | |||
dateAxis.setLabels(new String[] { metrics.get(0).name, | |||
metrics.get(metrics.size() / 2).name, metrics.get(metrics.size() - 1).name }); | |||
provider.addAxis(dateAxis); | |||
ChartAxis commitAxis = new ChartAxis(ChartAxisType.LEFT); | |||
commitAxis.setLabels(new String[] { "", | |||
String.valueOf((int) WicketUtils.maxValue(metrics)) }); | |||
provider.addAxis(commitAxis); | |||
provider.setLineStyles(new LineStyle[] { new LineStyle(2, 4, 0), new LineStyle(0, 4, 1) }); | |||
provider.addShapeMarker(new ShapeMarker(MarkerType.CIRCLE, Color.decode("#002060"), 1, -1, 5)); | |||
add(new SecureChart("commitsChart", provider)); | |||
} else { | |||
add(WicketUtils.newBlankImage("commitsChart")); | |||
private Charts createCharts(List<Metric> metrics) { | |||
Charts charts = new Flotr2Charts(); | |||
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd"); | |||
String displayFormat = "MMM dd"; | |||
if(metrics.size() > 0 && metrics.get(0).name.length() == 7){ | |||
df = new SimpleDateFormat("yyyy-MM"); | |||
displayFormat = "yyyy MMM"; | |||
} | |||
df.setTimeZone(getTimeZone()); | |||
// build google charts | |||
Chart chart = charts.createLineChart("commitsChart", getString("gb.activity"), "day", getString("gb.commits")); | |||
chart.setDateFormat(displayFormat); | |||
for (Metric metric : metrics) { | |||
Date date; | |||
try { | |||
date = df.parse(metric.name); | |||
} catch (ParseException e) { | |||
logger.error("Unable to parse date: " + metric.name); | |||
return charts; | |||
} | |||
chart.addValue(date, (int)metric.count); | |||
if(metric.tag > 0 ){ | |||
chart.addHighlight(date, (int)metric.count); | |||
} | |||
} | |||
charts.addChart(chart); | |||
return charts; | |||
} | |||
} |
@@ -0,0 +1,21 @@ | |||
.flotr-mouse-value { | |||
opacity: 1 !important; | |||
background-color: #FFFFFF !important; | |||
color: #666 !important; | |||
font-size: 10px; | |||
border: 1px solid #ddd; | |||
} | |||
.flotr-legend-label{ | |||
opacity: 1 !important; | |||
background-color: #FFFFFF !important; | |||
color: #666 !important; | |||
font-size: 10px; | |||
padding: 2px; | |||
border-style: none !important; | |||
} | |||
.flotr-title { | |||
text-align: left !important; | |||
font-size: 10px !important; | |||
} |