Recode 'Task Completation Lead/Lag' chart using jqplot4java

FEA: ItEr76S15OrganizingPerProjectDashboard
This commit is contained in:
Diego Pino 2012-04-30 01:06:09 +02:00
parent a35a468530
commit 4664896693
2 changed files with 80 additions and 151 deletions

View file

@ -27,6 +27,7 @@ import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.libreplan.business.orders.entities.Order;
@ -45,12 +46,14 @@ import org.zkoss.zul.Window;
import br.com.digilabs.jqplot.Chart;
import br.com.digilabs.jqplot.JqPlotUtils;
import br.com.digilabs.jqplot.chart.BarChart;
import br.com.digilabs.jqplot.chart.PieChart;
import br.com.digilabs.jqplot.elements.Serie;
/**
* @author Nacho Barrientos <nacho@igalia.com>
* @author Diego Pino García <dpino@igalia.com>
*
*
* Controller for dashboardfororder view
*/
@Component
@ -113,14 +116,27 @@ public class DashboardController extends GenericForwardComposer {
}
private void renderTaskCompletationLag() {
Map<Interval, Integer> taskCompletationData = dashboardModel
.calculateTaskCompletation();
TaskCompletationLag taskCompletation = TaskCompletationLag.create();
for (Interval each : taskCompletationData.keySet()) {
Integer value = taskCompletationData.get(each);
taskCompletation.data(each.toString(), value);
}
taskCompletation.render();
final String divId = "task-completation-lag";
BarChart<Integer> barChart;
barChart = new BarChart<Integer>("Task Completation Lead/Lag");
barChart.setFillZero(true);
barChart.setHighlightMouseDown(true);
barChart.setStackSeries(false);
barChart.setBarMargin(30);
barChart.addSeries(new Serie("Tasks"));
TaskCompletationData taskCompletationData = TaskCompletationData
.create(dashboardModel);
barChart.setTicks(taskCompletationData.getTicks());
barChart.addValues(taskCompletationData.getValues());
barChart.getAxes().getXaxis()
.setLabel(_("Number of Days / Days Interval"));
renderChart(barChart, divId);
}
private void renderTasksSummary() {
@ -189,9 +205,9 @@ public class DashboardController extends GenericForwardComposer {
}
/**
*
*
* @author Diego Pino García <dpino@igalia.com>
*
*
*/
static class GlobalProgress {
@ -262,7 +278,7 @@ public class DashboardController extends GenericForwardComposer {
/**
* The order of the ticks is taken from the keys in current
*
*
* @return
*/
public String getTicks() {
@ -279,9 +295,9 @@ public class DashboardController extends GenericForwardComposer {
}
/**
*
*
* @author Diego Pino García <dpino@igalia.com>
*
*
*/
static class Series {
@ -314,61 +330,48 @@ public class DashboardController extends GenericForwardComposer {
}
static class TaskCompletationLag {
/**
*
* @author Diego Pino García<dpino@igalia.com>
*
*/
static class TaskCompletationData {
private final String id = "task_completation_lag";
private final IDashboardModel dashboardModel;
private final Map<String, Integer> data = new LinkedHashMap<String, Integer>();
private TaskCompletationLag() {
private Map<Interval, Integer> taskCompletationData;
private TaskCompletationData(IDashboardModel dashboardModel) {
this.dashboardModel = dashboardModel;
}
public static TaskCompletationLag create() {
return new TaskCompletationLag();
public static TaskCompletationData create(IDashboardModel dashboardModel) {
return new TaskCompletationData(dashboardModel);
}
public void data(String interval, Integer value) {
data.put(interval, value);
private Map<Interval, Integer> getData() {
if (taskCompletationData == null) {
taskCompletationData = dashboardModel
.calculateTaskCompletation();
}
return taskCompletationData;
}
public void render() {
String _data = JSONHelper.values(data);
String ticks = JSONHelper.keys(data);
String command = String.format("%s.render(%s, %s);", id, _data,
ticks);
Clients.evalJavaScript(command);
public String[] getTicks() {
Set<Interval> intervals = getData().keySet();
String[] result = new String[intervals.size()];
int i = 0;
for (Interval each : intervals) {
result[i++] = each.toString();
}
return result;
}
public Collection<Integer> getValues() {
return getData().values();
}
}
static class JSONHelper {
public static String format(Map<String, Integer> data) {
List<String> result = new ArrayList<String>();
for (String key : data.keySet()) {
Integer value = data.get(data);
result.add(String.format("[\"%s\", %d]", key, value));
}
return String.format("'[%s]'", StringUtils.join(result, ','));
}
public static String keys(Map<String, ?> map) {
List<String> result = new ArrayList<String>();
for (String each : map.keySet()) {
result.add(String.format("\"%s\"", each));
}
return String.format("'[%s]'", StringUtils.join(result, ','));
}
public static String values(Map<?, Integer> map) {
List<String> result = new ArrayList<String>();
for (Integer each : map.values()) {
result.add(each.toString());
}
return String.format("'[%s]'", StringUtils.join(result, ','));
}
}
}
}

View file

@ -27,7 +27,7 @@
<!-- VERY IMPORTANT!!
Don't include any HTML or Javascript code here because apparently this view, Dashboard view, will be rendered OK,
but it creates a side effect in the other views. If you include HTML here, go to Dashboard and later to other view, a big
chunk of space will appear on the top of the view
chunk of space will appear on the top of the view
-->
<div self="@{define(content)}" height="100%" style="overflow:visible">
@ -39,12 +39,12 @@
<div id="projectDashboardChartsDiv" sclass="dashboards-container" height="100%" width="100%">
<!-- Progress -->
<groupbox closable="false">
<caption label="${i18n:_('Progress')}" />
<groupbox closable="false">
<caption label="${i18n:_('Progress')}" />
<hbox>
<n:div id="global-progress" style="height:200px; width:500px;"></n:div>
<n:div id="task-status" style="height:200px; width:400px; margin-left: 100px;"></n:div>
<n:div id="global-progress" style="height:200px; width:500px;"></n:div>
<n:div id="task-status" style="height:200px; width:400px; margin-left: 100px;"></n:div>
<!-- Tasks summary -->
<grid id="gridTasksSummary" style="margin-top: 50px;" width="300px">
<auxhead>
@ -73,18 +73,18 @@
</row>
</rows>
</grid>
</hbox>
</groupbox>
</hbox>
</groupbox>
<!-- Time -->
<groupbox closable="false">
<caption label="${i18n:_('Time')}" />
<groupbox closable="false">
<caption label="${i18n:_('Time')}" />
<hbox>
<n:div id="task-completation-lag" style="height:200px; width:560px;"></n:div>
<n:div id="deadline-violation" style="height:200px; width:400px; margin-left: 100px;"></n:div>
<n:div id="margin-with-deadline" style="height:200px; width:400px; margin-left: 100px;"></n:div>
</hbox>
</groupbox>
<n:div id="task-completation-lag" style="height:200px; width:580px;"></n:div>
<n:div id="deadline-violation" style="height:200px; width:400px; margin-left: 100px;"></n:div>
<n:div id="margin-with-deadline" style="height:200px; width:400px; margin-left: 100px;"></n:div>
</hbox>
</groupbox>
</div>
@ -101,22 +101,8 @@
<!-- The variable for containing the 'global progress' has to be global and created before defer -->
<script type="text/javascript">
var global_progress = { };
var task_completation_lag = { };
</script>
<n:style type="text/css">
.tooltip {
display:none;
position:absolute;
border:1px solid #333;
background-color:#161616;
border-radius:5px;
padding:10px;
color:#fff;
font-size:12px Arial;
}
</n:style>
<!-- Configure the parameters for the 'global progress' chart. The object contains a method 'render' that
is called from the Java file once all objects in the view have been created -->
<script type="text/javascript" defer="true">
@ -139,7 +125,7 @@
label: "Progress percentage per progress type"
},
yaxis: {
renderer: $.jqplot.CategoryAxisRenderer,
renderer: $.jqplot.CategoryAxisRenderer,
ticks: ['1','2','3'],
tickOptions: {
showGridline: false,
@ -161,77 +147,17 @@
this.axes.yaxis.ticks = jQuery.parseJSON(ticks);
}
if (series !== undefined) {
this.series = jQuery.parseJSON(series);
this.series = jQuery.parseJSON(series);
}
this.plot = $.jqplot(this.id, jQuery.parseJSON(data), this);
}
};
task_completation_lag = {
id: 'task-completation-lag',
title: 'Task completation lag',
data: [],
seriesDefaults:{
renderer:$.jqplot.BarRenderer,
rendererOptions: {
fillToZero: true
}
},
axesDefaults: {
tickRenderer: $.jqplot.CanvasAxisTickRenderer ,
tickOptions: {
angle: -30,
fontSize: '10pt'
}
},
axes: {
xaxis: {
label: 'Number of Days / Days Interval',
renderer: $.jqplot.CategoryAxisRenderer,
},
},
render: function(data, conf) {
if (conf.ticks !== undefined) {
this.axes.xaxis.ticks = jQuery.parseJSON(conf.ticks);
}
if (conf.titles !== undefined) {
this.axes.xaxis.ticks = jQuery.parseJSON(conf.ticks);
}
this.plot = $.jqplot(this.id, [jQuery.parseJSON(data)], this);
this.attachTooltip();
},
attachTooltip: function() {
var node = $('#' + this.id);
node.bind('jqplotDataHighlight',
function (ev, seriesIndex, pointIndex, data) {
var x = ev.pageX - node.offset().left;
var y = ev.pageY - node.offset().top;
var tooltip = $('<span class="tooltip"></span>');
tooltip.text(data[1]).appendTo(node);
tooltip.css({'top': y, 'left': x, 'position': 'absolute'});
tooltip.fadeIn('slow');
}
);
node.bind('jqplotDataUnhighlight',
function (ev) {
$('.tooltip').remove();
}
);
node.mousemove(function(ev) {
var x = ev.pageX - node.offset().left;
var y = ev.pageY - node.offset().top;
$('.tooltip').css({'top': y, 'left': x, 'position': 'absolute'})
});
}
};
]]>
</script>
<!-- Include jqPlot styles -->
<n:link class="include" rel="stylesheet" type="text/css" href="/libreplan-webapp/jqplot/jquery.jqplot.min.css" />
<n:link class="include" rel="stylesheet" type="text/css" href="/libreplan-webapp/jqplot/jquery.jqplot.min.css" />
<!-- Include jqPlot library and additional plugins -->
<n:script type="text/javascript" src="/libreplan-webapp/jqplot/jquery.js"></n:script>