Browse Source

Merged #43 "Switch to flotr2 graphs from GoogleCharts"

tags/v1.5.0
James Moger 10 years ago
parent
commit
37ee4854c4

src/main/java/com/gitblit/wicket/charting/GoogleChart.java → src/main/java/com/gitblit/wicket/charting/Chart.java View File

@@ -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;
}
}

+ 48
- 0
src/main/java/com/gitblit/wicket/charting/Charts.java View File

@@ -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);

}

+ 167
- 0
src/main/java/com/gitblit/wicket/charting/Flotr2BarChart.java View File

@@ -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);
}

}

+ 76
- 0
src/main/java/com/gitblit/wicket/charting/Flotr2Charts.java View File

@@ -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);
}
}

+ 150
- 0
src/main/java/com/gitblit/wicket/charting/Flotr2LineChart.java View File

@@ -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);
}

}

+ 112
- 0
src/main/java/com/gitblit/wicket/charting/Flotr2PieChart.java View File

@@ -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, "});");
}
}

}

+ 0
- 67
src/main/java/com/gitblit/wicket/charting/GoogleCharts.java View File

@@ -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');
}
}

+ 0
- 60
src/main/java/com/gitblit/wicket/charting/GoogleLineChart.java View File

@@ -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, "");
}
}

+ 0
- 86
src/main/java/com/gitblit/wicket/charting/GooglePieChart.java View File

@@ -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, "");
}
}

+ 0
- 633
src/main/java/com/gitblit/wicket/charting/SecureChart.java View File

@@ -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());
}
}

+ 0
- 102
src/main/java/com/gitblit/wicket/charting/SecureChartDataEncoding.java View File

@@ -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);
}

+ 14
- 13
src/main/java/com/gitblit/wicket/pages/ActivityPage.java View File

@@ -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);

+ 8
- 6
src/main/java/com/gitblit/wicket/pages/DashboardPage.java View File

@@ -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);

+ 6
- 6
src/main/java/com/gitblit/wicket/pages/MetricsPage.html View File

@@ -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>

+ 58
- 65
src/main/java/com/gitblit/wicket/pages/MetricsPage.java View File

@@ -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);
}
}

+ 2
- 2
src/main/java/com/gitblit/wicket/pages/MyDashboardPage.html View File

@@ -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>

+ 6
- 5
src/main/java/com/gitblit/wicket/pages/OverviewPage.java View File

@@ -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));
}

+ 1
- 1
src/main/java/com/gitblit/wicket/pages/SummaryPage.html View File

@@ -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 -->

+ 45
- 37
src/main/java/com/gitblit/wicket/pages/SummaryPage.java View File

@@ -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;
}
}

+ 21
- 0
src/main/resources/flotr2/flotr2.custom.css View File

@@ -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;
}

+ 10
- 0
src/main/resources/flotr2/flotr2.min.js
File diff suppressed because it is too large
View File


Loading…
Cancel
Save